Where are Java strings stored

In the morning, I saw the group of friends discussing the topic of where the Java string is. I was interested in the vegetable chicken who roughly witnessed the virtual machine, studied it and sorted out this blog

Where does the string exist

Here is a summary of what you agree:

  • If you use a constant method, the object will be stored in the constant pool (permanent generation)
  • If you use the new method, the object will be stored in the heap

The following code reveals the situation:

  • Use the form of constant for the same object
  • Use new for different objects
  • Even if the method of the object created by the constant is called, the object will not change: the description is an object, not a set of arrays
public class TestString {
    public static void main(String[] args) {
        String a="Aa";
        String b="Aa";
        String c=new String("Aa");
        String d=new String("Aa");


Process finished with exit code 0

That's the simple rule. I hope it's enough to see here
But if you look at the specific implementation, you will find it wonderful, such as Java string constant pool and intern method, which are described in detail below

Further understanding

Before we start, let's look at the magic method in this String

 * Returns a canonical representation for the string object. 
 * <p> 
 * A pool of strings, initially empty, is maintained privately by the 
 * class <code>String</code>. 
 * <p> 
 * When the intern method is invoked, if the pool already contains a 
 * string equal to this <code>String</code> object as determined by 
 * the {@link #equals(Object)} method, then the string from the pool is 
 * returned. Otherwise, this <code>String</code> object is added to the 
 * pool and a reference to this <code>String</code> object is returned. 
 * <p> 
 * It follows that for any two strings <code>s</code> and <code>t</code>, 
 * <code>s.intern()&nbsp;==&nbsp;t.intern()</code> is <code>true</code> 
 * if and only if <code>s.equals(t)</code> is <code>true</code>. 
 * <p> 
 * All literal strings and string-valued constant expressions are 
 * interned. String literals are defined in section 3.10.5 of the 
 * <cite>The Java&trade; Language Specification</cite>. 
 * @return  a string that has the same contents as this string, but is 
 *          guaranteed to be from a pool of unique strings. 
public native String intern(); 

This method is a native method, but the annotation is very clear. If there is a current string in the constant pool, the current string will be returned directly. If there is no such string in the constant pool, the string will be put into the constant pool and then returned.

Remember this wonderful method first. I suggest you think about this logic.

Then learn about jdk1 6 and jdk1 Differences between constant pools in 7

Take a look at jdk1 six

In jdk1 In jdk6, the constant pool is an independent area. The constant pool in jdk6 is placed in the Perm area, which is completely separated from the normal JAVA Heap area.
Some people may not understand it very well
Let's put it another way:
String of "string" type is stored in constant pool, and constant pool and Java heap are two different parts.
in other words,

  • Stored in the constant pool and stored in the heap, the implementation is different.
  • The constant pool is 4M by default, so there is consumption. Throw Java lang.OutOfMemoryError: PermGen space

Come to jdk1 seven
At jd.k1 In 7, this area called Perm is cancelled. The constant pool is the heap. The String object in the constant pool and the String object of the heap exist in the same area. In the jdk7 version, the String constant pool has been moved from the Perm area to the normal Java Heap area. The reason for moving is that the Perm area is too small. Of course, according to the news, jdk8 has directly cancelled the Perm area and created a new meta area. JDK developers should think that the Perm area is no longer suitable for the development of JAVA.

Problem discovery

Based on the above, it is not difficult to find that in jdk1 6 and jdk1 If you run the same code in 7, the result will be different

public static void main(String[] args) {
    String s = new String("1");
    String s2 = "1";
    System.out.println(s == s2);

    String s3 = new String("1") + new String("1");
    String s4 = "11";
    System.out.println(s3 == s4);

In jdk1 In 6, the constant pool and heap are clearly separated
So we can infer:

  • The s object is new, so it is in the heap
  • The s2 object is a constant and exists in the constant pool
  • S and S2 are stored in different locations, s= s2
  • s3 adds two string objects and calls the intern method, but the storage locations are different. s3 must be different from s4

The result is false

In jdk1 In 7, because there is no special area of perm

  • The s object is new, so it is in the heap
  • The s2 object is a constant and exists in the constant pool
  • S and S2 are stored in different locations, s= s2
  • The value of s3 object is "11", but it is spliced by two "1", so there will only be "1" in the constant pool instead of "11" (this is very important)
  • The s3intern method generates "11" in the constant pool. Because there is no "11" string in the constant pool at this time, the general practice is to generate an "11" object in the constant pool as shown in the figure of jdk6. The key point is that the constant pool in jdk7 is not in the Perm area, which has been adjusted. There is no need to store another object in the constant pool. You can directly store references in the heap. This reference points to the object referenced by s3. That is, the reference address is the same.
  • s4 use constant pool "11" directly
  • s3==s4

Reference articles

Tags: Java JDK

Posted by wipe on Mon, 16 May 2022 20:48:52 +0300