11

I have known that JVM maintains a string literal pool to increase performance and maintain JVM memory and learned that string literal is maintained in the string pool. But I want to clarify something related to the string pool and string object created on the heap.

Please correct me if my explanation is wrong.

String s = "abc";

If the above line is executed, "abc" string literal is added to the string pool if it does not exist in the pool. And string object is created on the heap and a reference s will point to the literal in the pool.

Questions:

  1. Does this code create string object on the heap every time it is executed?
  2. Does string literal pool maintain only string literals or does it maintain string object as well?
  3. When does JVM decide that it needs to add string literal to the string pool? does it decide in the compile time or runtime?

I am not sure where exactly string object is created if it points to a string literal in the pool.

Thanks.

Sahil Muthoo
  • 12,033
  • 2
  • 29
  • 38
user826323
  • 2,248
  • 6
  • 43
  • 70

4 Answers4

5

There is no "literal pool". Interned Strings are just normal heap objects. They may end up in the PermGen, but even then, they could eventually be garbage-collected.

The class file has a constant pool, which contains the String literals used in the class. When the class is loaded, String objects are created from that data, which is probably very similar to what String#intern does.

Does this code create string object on the heap every time it is executed?

No. There will be one String object that is being reused. It has been created when the class was loaded.

Does string literal pool maintain only string literals or does it maintain string object as well?

You can intern Strings as well. I assume that they are treated more or less the same.

When does JVM decide that it needs to add string literal to the string pool? does it decide in the compile time or runtime?

Literals are always "pooled". Other Strings need to have "intern" called on them. So in a way, the decision is made at compile-time.

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • If the interned string stays in the PernGen, how about the string object that is created with "new" keyword? is it created in the young generation? – user826323 Nov 08 '11 at 05:24
  • 1
    All new objects are created in the young generation. If they stay alive long enough they will migrate elsewhere. – Thilo Nov 08 '11 at 06:17
  • *"When the class is loaded, String objects are created from that data, which is probably very similar to what String#intern does."* Not just similar: *"...string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method `String.intern`."* [(spec)](https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5) – T.J. Crowder Mar 21 '17 at 11:10
4

Quoting documentation for String.intern()(emphasis mine)

All literal strings and string-valued constant expressions are interned. String literals are defined in §3.10.5 of the Java Language Specification


A pool of strings, initially empty, is maintained privately by the class String.

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.


Thus,

Does this code create string object on the heap every time it is executed?

Only one object is created for each unique interned string. All references share this immutable object.

Does string literal pool maintain only string literals or does it maintain string object as well?

There are no 'Literal Objects'. Literal string expressions when converted, are stored as regular String objects.Also, the pool contains all interned string objects. Both implicit (by using a string literal expression) and explicit (by calling .intern() on a String object).

When does JVM decide that it needs to add string literal to the string pool? does it decide in the compile time or runtime?

I'm not sure.

Sahil Muthoo
  • 12,033
  • 2
  • 29
  • 38
1

I think there's something fundamental you're missing: the interned strings pool only contains String objects. Literals are not some sort of special object; at runtime they are just another String object.

Plus you can intern any String you want using String.intern(); it doesn't have to originate from a literal.

So regarding your questions:

  1. No, there will be one String object allocated when the class is loaded.
  2. It doesn't maintain any literals but rather String objects that were interned. Usually, those come from literals but in reality it could be any compile-time constant expression (String constant = "abc" + "def" would result in one String object "abcdef" at runtime).
  3. They are compiled into the class file. So they are decided at compile time but obviously the objects themselves are created at runtime.
Mark Peters
  • 80,126
  • 17
  • 159
  • 190
  • 1
    *"Literals are not some sort of special object; at runtime they are just another String object."* *Literals* aren't objects at all; they're a way of writing objects (in this case) in source code. The concept of a literal is a source code concept. The *result* of a literal is a `String` object. (You make this distinction nicely later.) – T.J. Crowder Mar 21 '17 at 11:07
1

Does this code create string object on the heap every time it is executed?

Nope. Once created in the literal pool. The same referred again and again.

Does string literal pool maintain only string literals or does it maintain string object as well?

All are objects only, but objects created via assignment are put in pool where as the one created via new operator are put on heap.

When does JVM decide that it needs to add string literal to the string pool? does it decide in the compile time or runtime?

Whenever JVM comes across an expressions like

String str="Hello"; (string literal) or
String str="Hel" + "lo"; (string constant expression).

and the resultant string (str in this case) is not the pool, then in all such cases it adds the new string in the pool. This off course happens at runtime.

Check out this link.

Community
  • 1
  • 1
Santosh
  • 17,667
  • 4
  • 54
  • 79
  • No. By the time the JVM sees a string literal when executing code such as in your answer the literals are already interned, placed there by the compiler and classloader. Constant expressions are evaluated at compile time. – user207421 Oct 22 '16 at 07:19
  • Please provide any substantiating link/article/example to prove you point. – Santosh Oct 24 '16 at 10:06