Sunday, 4 December 2011

String constant pool in Java

String constant pool is for efficient memory management in java.All the objects in java except string objects are managed in heap memory area.But in the case of string objects there is a little difference .To cut down the number of String objects created in the JVM, the String class keeps a pool of strings. Each time your code create a string literal, the JVM checks the string literal pool first. If the string already exists in the pool, a reference to the pooled instance returns. If the string does not exist in the pool, a new String object instantiates, then is placed in the pool. Java can make this optimization since strings are immutable and can be shared without fear of data corruption.
In java every object instance is on the heap, so every String instance is as well. However if you have a string literal, or string constant in your source code, java will during compilation gather all of them and pre-create them (on the heap) and store references to them in the string literal pool.



The advantages of this are
  • Duplicates are removed, because strings are immutable they can safely be shared. This means less overall memory usage.
  • You can safely compare them with == instead of the more expensive equals, since they are guaranteed to be the same instance
The disadvantage of this is:
  • References to the strings in the string literal pool are kept for the duration of the program. This means they will never be garbage collected. If you have large string literals, that you only use temporarily, this might actually increase memory usage of your program, but this is hardly ever anything to worry about
Now if you create a string with new String("java") it will not be added to the string literal pool, but it will be created as a new object on the heap. This means you cannot compare it with == any longer, you have to use equals() (if content equality is what you are looking for)

String objects can be created in two different ways

Using a string literal or constant expression. For example,

String str="Java"; (string literal) or
String str="Ja" + "va"; (string constant expression).

Using the new operator. For example,

String str = new String("Java");

Let us discuss the difference between these string creations.

When a .java file is compiled into a .class file, any String literals are noted in a special way, just as all constants are. When a class is loaded (note that loading happens prior to initialization), the JVM goes through the code for the class and looks for String literals. When it finds one, it checks to see if an equivalent String is already referenced from the heap. If not, it creates a String instance on the heap and stores a reference to that object in the constant table. Once a reference is made to that String object, any references to that String literal throughout your program are simply replaced with the reference to the object referenced from the String Literal Pool.
Take a look at this example:

public class Example
{
  public static void main(String[] args)
  {
   String s1 = "java";
   String s2 = "java";
   System.out.println(s1.equals(s2));
   System.out.println(s1== s2);
  }
}
// Output

true
true
In the above example after the class loading,JVM searches the string constant table for a reference of the string object that contained the word “java”.If exist it will reuse that object else it will create a new string object which contained the word “java” and add a reference of it in string constant pool and assign that reference to the local variable.
So,in the example shown above, there would be only one entry in the String Literal Pool,which would refer to a String object that contained the word "java". Both of the local variables, s1 and s2, would be assigned a reference to that single String object. You can see that this is true by looking at the output of the above program. While the equals() method checks to see if the String objects contain the same data ("java"), the == operator, when used on objects, checks for referential equality - that means that it will return true if and only if the two reference variables refer to the exact same object. In such a case, the references are equal. From the above output, you can see that the local variables, s1 and s2, not only refer to Strings that contain the same data, they refer to the same object.
Constructing Strings using the "new" keyword implies a different sort of behavior.

Take a look at this example:
public class Example
{
 public static void main(String[] args)
 {
   String s1 = "java"; 
   String s2 = new String("java"); 
   System.out.println(s1.equals(s2));
   System.out.println(s1 == s2); 
 }
}
// Output
true
false
If you are using the keyword new to create a string object it will create a string object at runtime rather than using the one from the constant table.In the above example s2 will create a string object at runtime which contained the word java rather than reusing the one from the string constant pool.Here both s1 and s2 referencing different string objects which contained the word “java”.Therefore (s1==s2) returns false and s1.equals(s2) returns true.

Usage of the String.inturn() method
A JVM has a string pool where it keeps at most one object of any String. String literals always refer to an object in the string pool. String objects created with the new operator do not refer to objects in the string pool but can be made to using String's intern() method. The java.lang.String.intern() returns an interned String, that is, one that has an entry in the global String pool. If the String is not already in the global String pool, then it will be added.

For example
public class Program
{
public static void main(String[] args)
{
String s1 = "Hello";
String s2 = new Strinn(“Hello”);
String s3 = s2.intern();

// Determine which strings are equivalent using the ==
// operator
System.out.println("s1 == s2? " + (s1 == s2));
System.out.println("s1 == s3? " + (s1 == s3));
}
}

The output is

s1 == s2? false
s1 == s3? true
Garbage Collection 
Unlike most objects, String literals always have a reference to them from the String Literal Pool. That means that they always have a reference to them and are, therefore, not eligible for garbage collection.Using new String("Java") will always create a new object on the heap, (so can be duplicated) but then can be garbage collected if no longer used.

public class Example
{
    public static void main(String[] args)
    {
        String s1 = "Java";
        String s2 = new String("Java");
        s1 = s2 = null;
    }
} 

In the above example s1 is not eligible for garbage collection bacause string
literals always have a reference in string constant pool.

      
 
 

1 comment:

  1. where is this string literal pool stored in memory ?????
    means is it stored in heap??stack ??or method area??or somewhere else??

    ReplyDelete