Questions About Java'S String Pool

Questions about Java's String pool

If you use the new keyword, a new String object will be created. Note that objects are always on the heap - the string pool is not a separate memory area that is separate from the heap.

The string pool is like a cache. If you do this:

String s = "abc";
String p = "abc";

then the Java compiler is smart enough to make just one String object, and s and p will both be referring to that same String object. If you do this:

String s = new String("abc");

then there will be one String object in the pool, the one that represents the literal "abc", and there will be a separate String object, not in the pool, that contains a copy of the content of the pooled object. Since String is immutable in Java, you're not gaining anything by doing this; calling new String("literal") never makes sense in Java and is unnecessarily inefficient.

Note that you can call intern() on a String object. This will put the String object in the pool if it is not already there, and return the reference to the pooled string. (If it was already in the pool, it just returns a reference to the object that was already there). See the API documentation for that method for more info.

See also String interning (Wikipedia).

Need to know about String, String Constant pool and String intern method

I will assume that in each example below you load and execute the code exactly once, in a new JVM each time. (I will also assume that nowhere else in your code do you use the literal "Java" ... since that would complicate things.)


1) Say if there are no strings in the String constant pool, and if i
say,

String s = "Java";

Then how many objects will be created ?

One string is created and added to the pool when method is loaded.


2) Now again nothing in the pool, and i say,

String s = new String("Java");

Now how many objects will be created.

One string is created and added to the pool when method is loaded.

A second string is created by the new when the code is run, and it is NOT added to the pool.


3) Now again nothing in the pool, and i say,

String s = new String("Java");
s.intern();

What will the intern method do ?

One string is created and added to the pool when method is loaded.

A second string is created by the new, and it is NOT added to the pool.

The intern call returns the first string. (You don't keep the reference ...)


4) Now again nothing in the pool, and i say,

String s = new String("Java");
String s1 = s.intern();

What will happen now?

Same as example 3. Thus, s1 will hold a reference to the String object that represents the "Java" string literal.


I read in SCJP5 Kathy Sierra book, that when you create a String with new, then 2 objects are created, one on the heap and one in the pool.

I doubt that the book said that exactly. (You are paraphrasing, and I think you have paraphrased somewhat inaccurately.)

However, your paraphrasing is roughly correct, though (an this is important!) the string object representing the literal is created and added to the pool when the code fragment is loaded1, not when it is executed.


And to address another point of confusion:

"What i actually meant was that from the answer that you gave, it seems that a String will always be added in the String constant pool."

That is incorrect. It is a false generalization.

While it is true for all 4 of the cases above, it will not be true for others. It depends on where the original string came from. In typical applications, most text data is read from a file, socket, or a user interface. When that happens, the strings are created from arrays of characters, either directly or via a library call.

Here is a simple (but unrealistic) example that shows creating a String from its component characters.

String s = new String(new char[]{'J', 'a', 'v', 'a'});

In the snippet above, only one String is created, and it is NOT in the String pool. If you wanted the resulting string to be in the string pool you need to explicitly call intern something like this:

String s = new String(new char[]{'J', 'a', 'v', 'a'});
s = s.intern();

... which will (if necessary) create a second string in the string pool2.


1 - Apparently, in some JVMs creation and interning string literals is done lazily, so it is not possible to say with 100% certainty when it actually happens. However, it will only occur once (per class that references the literal), no matter how many times the code fragment is executed by the JVM.

2 - There is no way to new a string into the string pool. It would actually be a violation of the JLS. The new operation is specified by the JLS as always creating a new object.

Java String Pool with String constructor and the intern function

You wrote

String c = new String("foo"); // Creates a new string in the heap

I read somewhere that even when using the constructor, the String Pool is being used. It
will insert the string into the String Pool and into the heap.

That’s somewhat correct, but you have to read the code correctly. Your code contains two String instances. First, you have the string literal "foo" that evaluates to a String instance, the one that will be inserted into the pool. Then, you are creating a new String instance explicitly, using new String(…) calling the String(String) constructor. Since the explicitly created object can’t have the same identity as an object that existed prior to its creation, two String instances must exist.

Why does java create this duplicate string? It seems completely redundant to me since the strings in java are immutable.

Well it does so, because you told it so. In theory, this construction could get optimized, skipping the intermediate step that you can’t perceive anyway. But the first assumption for a program’s behavior should be that it does precisely what you have written.

You could ask why there’s a constructor that allows such a pointless operation. In fact, this has been asked before and this answer addresses this. In short, it’s mostly a historical design mistake, but this constructor has been used in practice for other technical reasons; some do not apply anymore. Still, it can’t be removed without breaking compatibility.

String s = new String("Hello");
s = s.intern();

Will the garbage collector delete the string that is outside the String Pool from the heap?

Since the intern() call will evaluate to the instance that had been created for "Hello" and is distinct from the instance created via new String(…), the latter will definitely be unreachable after the second assignment to s. Of course, this doesn’t say whether the garbage collector will reclaim the string’s memory only that it is allowed to do so. But keep in mind that the majority of the heap occupation will be the array that holds the character data, which will be shared between the two string instances (unless you use a very outdated JVM). This array will still be in use as long as either of the two strings is in use. Recent JVMs even have the String Deduplication feature that may cause other strings of the same contents in the JVM use this array (to allow collection of their formerly used array). So the lifetime of the array is entirely unpredictable.

Java String creation and String pool

Regardless of where you are using, all string literals saves in String pool. So the answer is YES.

String hello = new String("Hello");
>--------< goes to pool.

But the thing is that the h2 won't refer from that h :)



Related Topics



Leave a reply



Submit