views:

419

answers:

9

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 = ".";
+10  A: 

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.

Gareth Davis
Read http://kohlerm.blogspot.com/2009/01/is-javalangstringintern-really-evil.html
Jacques René Mesrine
intern() isn't evil...you just ain't going to need it
Gareth Davis
I've programmed in Java for years and only used intern() twice, while doing a very thorough performance optimization of some server-based software that needed to support as many sessions as possible. 99.99% of the time you should never use it, and if you do find a place where it makes sense, be sure to consider the impact on your permgen space: you only want to intern small, bounded sets of literals.
Jim Ferrans
Couldn't (and didn't) say it any better.
Gareth Davis
guys, String duplicates are the norm (not sure whether that was the original question. Jacques was so kind to already post a link to my blog. You can find examples of high number of String duplicates in popular applications such as Netbeans and Eclipse. String.intern() can be useful to avoid duplicates. There are are possible solutions, but they are usually less memory efficient
kohlerm
+2  A: 

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

jensgram
javac does the concatenation, so that "helloworld" is already interned.
Tom Hawtin - tackline
+7  A: 

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.

Laurence Gonsalves
Again, javac does the concatenation, so that "helloworld" is already interned. Use javap -c to see that.
Tom Hawtin - tackline
javac does the first concatenation, but not the latter. The question wasn't whether ("hello" + "world").intern() is equivalent to "helloworld". The question was whether that (interned) string is equivalent to "hello".intern() + "world".intern(). The answer is no because javac doesn't constant fold the latter expression into "helloworld" (presumably due to the intervening method calls), and concatenating two interned String objects together does not give you an interned string.
Laurence Gonsalves
+10  A: 

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 (e.g. 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.

Jon Skeet
Please read a snippet of my usage of intern.
Jacques René Mesrine
Interned Strings are reclaimed. The are on SUN JVM stored in permspace, which means they require a Full GC to be reclaimed
kohlerm
+2  A: 

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.

Green Techy
See updated question for a sample usage
Jacques René Mesrine
+2  A: 

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.

Darren Greaves
A: 

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/

ammoQ
A: 

The amount of strings you're using has no effect on the Permananent Generation of the JVM, since we're still talking about one class.

Robert Munteanu
They used to be created in the perm gen (not entirely sure what the current state is).
Tom Hawtin - tackline
If you're talking about PermGen I'm going to assume you're using the Sun JVM. May I ask which version?
Robert Munteanu
A: 

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" :)

Thorbjørn Ravn Andersen