I understand how String pool and intern() method works in java. Here is a brief introduction.
String.intern() in Java 6
In those good old days all interned strings were stored in the PermGen – the fixed size part of heap mainly used for storing loaded classes and string pool. Besides explicitly interned strings, PermGen string pool also contained all literal strings earlier used in your program (the important word here is used – if a class or method was never loaded/called, any constants defined in it will not be loaded).
The biggest issue with such string pool in Java 6 was its location – the PermGen. PermGen has a fixed size and can not be expanded at runtime. You can set it using -XX:MaxPermSize=96m option. As far as I know, the default PermGen size varies between 32M and 96M depending on the platform. You can increase its size, but its size will still be fixed. Such limitation required very careful usage of String.intern – you’d better not intern any uncontrolled user input using this method. That’s why string pooling at times of Java 6 was mostly implemented in the manually managed maps.
String.intern() in Java 7
Oracle engineers made an extremely important change to the string pooling logic in Java 7 – the string pool was relocated to the heap. It means that you are no longer limited by a separate fixed size memory area. All strings are now located in the heap, as most of other ordinary objects, which allows you to manage only the heap size while tuning your application. Technically, this alone could be a sufficient reason to reconsider using String.intern() in your Java 7 programs. But there are other reasons.
OK up to this point I am comfortable with how Strings are stored in memory until I came across this tool Java Visualizer. I wrote up following simple Java class to visualize how memory is allocated in a program.
public class A {
String iWillAlwaysBeOnHeap="I am on heap...!!!";
class Dummy{
private int dummyNumber;
Dummy(int dummyNumber)
{
this.dummyNumber=dummyNumber;
}
}
public static void main(String[] args) {
A a=new A();
a.lonelyMethod();
}
public void lonelyMethod()
{
String lostString="dangling";
String test=new String("dangling");
test.intern();
String duplicateLiteral="dangling";
Dummy dummy=new Dummy(4);
}
}
And I got the following results:
As you can see String literals and objects with the same values are repeated and stored on stack and heap space does not come into the picture for method local Strings. I was confused at first but then I searched and found out about escape analysis which is done by JDK 7 automatically. But in my code I have created a String object which should be stored on heap but it is on stack as you can see in visualizer output but my Dummy class object is stored on heap. I could not really grasp this behavior. How are method local strings treated differently than other objects and instance level Strings?