Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why concatenation of String object and string literal is created in heap? [duplicate]

Tags:

java

string

I have below Strings

String str1 = "Abc";//created in constant pool
String str2 = "XYZ";//created in constant pool
String str3 = str1 + str2;//created in constant pool
String str4 = new String("PQR");//created in heap
String str5 = str1.concat(str4);//created in heap 
String str6 = str1 + str4;//created in heap

Here I don't know why concatenation of Strings, one created in the constant pool, and the other in the heap, results in creating the new String in the heap. I don't know the reason, why does it happen?

like image 903
Yogesh Katkar Avatar asked Nov 13 '19 07:11

Yogesh Katkar


People also ask

What happens when an object is concatenated with a string?

Concatenation of two strings is always creating a new object of the string. To conform this thing you can do one thing that how it managed in memory heap and pool.

What are the 2 methods used for string concatenation?

There are two ways to concatenate strings in Java: By + (String concatenation) operator. By concat() method.

Why are strings stored on the heap?

PermGen space is limited space, the default size is just 64 MB. And it was a problem of creating and storing too many string objects in PermGen space. That's why the String pool is moved to a larger heap area. To make the java more memory efficient the concept of string literal is used.

What happens when you concatenate two strings in Java?

Concatenation is the process of combining two or more strings to form a new string by subsequently appending the next string to the end of the previous strings. In Java, two strings can be concatenated by using the + or += operator, or through the concat() method, defined in the java. lang. String class.


1 Answers

There is a bunch of dubious information in the comments, so I will give this a proper answer.

  1. There is actually no such thing as "the constant pool". You won't find this term in the Java Language Specification.

    (Perhaps you are getting your terminology confused with the Constant Pool which is the section of a .class file, and the corresponding per-class Runtime Constant Pool ... which is not visible to application programs. These are "specification artifacts" defined by the JVM spec for the purpose of defining the execution model of bytecodes. The spec does not require that they physically exist, though they typically do; e.g. in an Oracle or OpenJDK implementation.)

  2. There is a data structure in a running JVM called the string pool. The string pool is NOT mentioned by name in the JLS, but its existence is implied by string literal properties as specified by the JLS. The string pool is mentioned in the javadocs, and the JVM specification.

  3. The string pool will contain the String objects that represent the values of any string-valued constant expression used in an application. This includes string literals.

  4. The string pool has always been primarily a de-duping mechanism for strings. Applications are able to use this by calling the String.intern method.

  5. The string values in the Constant Pool (see above) are used to create the String objects that the application see:

    • A String object is created from the representation.
    • String.intern is called, returning the corresponding de-duped String object from the string pool.
    • That string becomes part of the classes Runtime Constant Pool; i.e. the Runtime Constant Pool for a class will include a reference to the String object in the string pool.
    • This process can happen eagerly or lazily depending on the Java implementation.
  6. The string pool is and has always been stored in the (or a) heap.

    • Prior to Java 7, string objects in the string pool were allocated in a special heap called the PermGen heap. In the earliest versions of Java it wasn't GC'ed. Then it was GC'ed only occasionally.

    • In Java 7 (not 8!) the string pool stopped using the PermGen heap and used the regular heap instead.

    • In Java 8 the PermGen heap was replaced (for some purposes!) by a different storage management mechanism called the Metaspace. Apparently, Metaspace doesn't hold Java objects. Rather, it holds code segments, class descriptors and other JVM internal data structures.

  7. In recent versions of Java (i.e. Java 8 u20 and later) the GC has another mechanism for de-duping strings that survive a given number of GC cycles.

  8. The behavior of strings (i.e. which ones are interned and which ones are not) is determined by the relevant parts of the JLS and the javadocs for the String class.

  9. All of the complexity is irrelevant if you follow one simple rule:

    Never use == to compare strings. Always use equals.


Now to deal with your example code:

String str1 = "Abc";               // string pool

String str2 = "XYZ";               // string pool

String str3 = str1 + str2;         // not string pool (!!)

String str3a = "Abc" + "XYZ";      // string pool 

String str4 = new String("PQR");   // not string pool (but the "PQR" literal is)

String str5 = str1.concat(str4);   // not string pool 

String str6 = str1 + str4;         // not string pool

String str7 = str6.intern();       // string pool

Why?

  • The values assigned to str1, str2 and str3a are all values of constant expressions; see below.
  • The value assigned to str3 is not the value of a constant expression according to the JLS.
  • str4 - the JLS says that new operator always creates a new object and new strings are not automatically interned
  • str5 - string operations apart from intern do not create objects in the string pool
  • str6 - ditto - equivalent to a concat call. The JLS also says that + produces a new string (except in the constant expression case).
  • str7 - the exception: see above. The intern call returns a object in the string pool.

Constant expressions include literals, concatenations involving literals, values of static final String constants, and a few other things. See JLS 15.28 for the complete list, but bear in mind that the string pool only holds string values.


The precise behavior of intern depends on the Java version. Consider this example:

char[] chars = // create an array of random characters
String s1 = new String(chars);
String s2 = s1.intern();

Let us assume that the random characters do not correspond to any previously interned string.

  • For older JVMs where interned strings were allocated in PermGen, the intern call in the example will (must) produce a new String object.

  • For newer JVMs, the intern can add the existing String object to the string pool data structure without having to create a new String object.

In other words, the truth of s1 == s2 depends on the Java version.

like image 98
Stephen C Avatar answered Oct 22 '22 12:10

Stephen C