简体   繁体   中英

Am I correctly interning my Strings?

I want to make sure I don't pummel the permgen space, so I'm carefully interning my strings.

Are these two statements equivalent ?

String s1 = ( "hello" + "world" ).intern(); 

String s2 = "hello".intern() + "world".intern();

UPDATE

How I framed my question was totally different from the actual application. Here's the method where I am using intern.

public String toAddress( Transport transport )
{
    Constraint.NonNullArgument.check( transport, "transport" );

    switch( transport )
    {
    case GOOGLE:
    case MSN:
        return ( transport.code() + PERIOD + _domain ).intern();
    case YAHOO:
    default:
        return _domain;
    }
}
private String _domain;  // is initialized during constructor
private static final String PERIOD = ".";

The best advice I can think of is: don't bother. Statically declared String's will be in the constant pool any how so unless you are dynamically creating a String that is...errr no I can't think of a reason.

I've been programming using Java since 97 and I've never actually used String.intern() .

EDIT: After seeing your update I really am of the opinion that you shouldn't be using intern(). Your method looks perfectly normal and there there is little or no reason to use intern().

My reason for this is that it is infect an optimisation and potentially a premature one at that, you are second guessing the garbage collector. If the just of you method is short lived then the resulting string will die the young generation very shortly afterwards in the next minor GC and if it isn't it'll be interned (for want of a better word) in the mature generation anyhow.

I guess the only time this could be a good idea is if you spend a bit of time with a profiler and prove that it makes a large difference to the performance of your application.

As jensgram says, the two statements are not equivalent. Two important rules:

  • Concatenating string literals in code ends up with a string constant, so these two statements are exactly equivalent (they'll produce identical bytecode):

     String x = "foo" + "bar": String x = "foobar"; 
  • String constants are interned automatically, you don't need to do it explicitly

Now, this concentrates on literals - are you actually calling intern on literals, or is your real use case somewhat different (eg interning values fetched from a database which you'll see frequently)? If so, please give us more details.

EDIT: Okay, based on the question edit: this could save some memory if you end up storing the return value of toAddress() somewhere that it'll stick around for a long time and you'll end up with the same address multiple times. If those aren't the case, interning will actually probably make things worse. I don't know for sure whether interned strings stick around forever, but it's quite possible.

This looks to me like it's unlikely to be a good use of interning, and may well be making things worse instead. You mention trying to save permgen space - why do you believe interning will help there? The concatenated strings won't end up in permgen anyway, unless I'm much mistaken.

No. Adding two interned strings together does not give you an interned string.

That said, it's pretty rare that one needs to "carefully intern one's strings". Unless you're dealing with huge numbers of identical strings, it's more trouble than it's worth.

I would say no. s1 adds "helloworld" to the pool, whereas s2 is made up of the two pooled strings "hello" and "world".

More info will help us to understand your query... Anyway...

If you manually want to intern for HelloWorld then go with first statement as in second statement you interning hello and world separately. Two statements are not identical at all.

You might want to have some form of proof (via profiling perhaps) that you are "pummelling the permgen space" before you write all your code like that.

Otherwise you may just be doing "premature optimisation" which is generally frowned upon. See http://en.wikipedia.org/wiki/Optimization_(computer_science)#When_to_optimize for more details on why this may be a bad thing.

In many cases, "carefully interning" your strings gives you nothing but some time wasted. Consider the following case:

void foobar(int x) {
  String s1 = someMethod(x).intern();
  ...
  ...
}

So s1 is interned, no (heap) space wasted? Wrong! Most likely, the intermediary result of someMethod(x) still exists somewhere on the heap and needs to be garbage collected. That's because someMethod() somehow constructed the string, and (unless it returns a literal) it did that on the heap. But then... better look up what the permgen space is used for. It's used for metadata about classes and (ooops) the String.intern table. By interning all your strings, you are doing exactly what you wanted to avoid: Pummel the permgen space.

More information here: http://www.thesorensens.org/2006/09/09/java-permgen-space-stringintern-xml-parsing/

你正在使用的字符串数量对JVM的Permananent Generation 没有影响,因为我们还在讨论一个

interning strings is basically a memory leak waiting to happen :(

Unless you have a very, very good reason[1] don't do it, but leave it to the JVM.

[1] As in, "Dear Boss, Please don't fire me. I have this profiling data to support my decision to use intern" :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM