[Java] stack memory, heap memory, String constant pool

stack memory


The basic data type variables and object reference variables defined in the function are stored in the stack memory. When the variables exit the scope, the data in the stack will be automatically released for subsequent use.

heap memory


newObjects and arrays created by keywords are stored in heap memory, and the memory allocated in this area is managed by the Java garbage collection mechanism .

When the reference variable in the stack memory is released due to exiting the scope, the corresponding data in the heap memory will become data garbage because there is no reference point and become inaccessible and become data garbage. At this time, it will be reclaimed by the garbage collection mechanism.

String constant pool


  1. Before the jdk1.7.0version, the Stringconstant pool was located in the method area (Method Area) in the memory allocation area of ​​the Java virtual machine .
  2. After the jdk1.7.0version, the Stringconstant pool was moved to heap memory.

For a Stringstring type, its references are stored on the stack, but if the value can be determined at compile time (such as double-quote assignment), the value will be stored in the Stringconstant pool, if it is passed through newIf a keyword is created, it will be saved in the heap, and newa few will be saved.

When using newkeywords to create a string, it will first go to the Stringconstant pool to check whether there is a string with the same content. If it does not exist, it will Stringalso create a copy in the constant pool first, and then create a copy in the heap; If it exists, only one copy will be created in the heap.

So, for String str = new String("Hello");this line of code, if the string does not exist in the constant pool "Hello", then this line of code actually creates two objects.

"Hello"Since every time for the same string new, there will be one more object with the same content in the heap, which may cause a waste of resources in some cases, so is there any newway to go to the Stringconstant pool to check whether there is the same content during the operation? The string, if there is a way to directly quote it?

At this time, we can use the intern()method. When newoperating, call this method to realize the above idea.

public class StringTest {

    public static void main(String[] args) {
            String a = new String("Hello");
            String b = new String("Hello").intern();
            System.out.println(b == a);
    }   
}
true

Example of String constant pool problem


At compile time, the concatenated string of constants is parsed as a string constant:

public class StringTest {

    public static void main(String[] args) {
            String a = "a1";
            String b = "a" + 1;
            String c = "a" + "1";
            System.out.println("a == b: " + (a == b));
            System.out.println("a == c: " + (a == c));
    }   
}
a == b:true
a == c:true

In the "+"connection of strings, if there is a reference to a string constant value , it cannot be determined at compile time, and memory space can only be allocated in the heap at runtime, but the final modifier can be used to modify the string constant value. reference, so that it is resolved to a constant value at compile time:

public class StringTest {

    public static void main(String[] args) {
            String a = "abcd";

            String b = "ab";
            final String bf = "ab";

            String d = b + "cd";
            String df = bf + "cd";

            System.out.println("a == d: " + (a == d));
            System.out.println("a == df: " + (a == df));
    }   
}
a == d: false
a == df: true

Strings that cannot be determined at compile time will allocate memory space in heap memory at runtime, and refer to objects in the heap. If the intern()method is used, it will refer Stringto objects in the constant pool:

public class StringTest {

    public static void main(String[] args) {
        String a = "a1";
        String b = new String("a1");
        String c = new String("a1").intern();
        System.out.println("a == b: " + (a == b));
        System.out.println("a == c: " + (a == c));
        System.out.println("b == c: " + (b == c));
    }   
}
a == b: false
a == c: true
b == c: false

Immutability of String type


Take a look at this code:

public class Test {

    public static void main(String[] args) {
        String a = "ab";
        String b = "cd";
        String c = "ef";
        String str = a + b + c;
    }   
}

Then let's take a look at the contents of the compiled bytecode file:

D:\>javap -c Test.class
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String ab
       2: astore_1
       3: ldc           #3                  // String cd
       5: astore_2
       6: ldc           #4                  // String ef
       8: astore_3
       9: new           #5                  // class java/lang/StringBuilder
      12: dup
      13: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
      16: aload_1
      17: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      20: aload_2
      21: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      24: aload_3
      25: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      28: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      31: astore        4
      33: return
}

You will find that it is actually equivalent to this code:

public class Test {

    public static void main(String[] args) {
        String a = "ab";
        String b = "cd";
        String c = "ef";
        StringBuilder builder = new StringBuilder();
        builder.append(a);
        builder.append(b);
        builder.append(c);
        String str = builder.toString();
    }   
}

Then let's take a look at StringBuilderthe methods in the class toString():

    @Override
    public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }

You will find that whenever we use "+"to splicing strings, an StringBuilderobject will be generated, and then the object will be discarded when it is used up. It may not be obvious to waste resources if we do this once or twice, so what about when we use loop splicing? ? For example, if the loop is repeated "+="100 times, 100 StringBuilderobjects will be created, which is a serious waste of resources.

So why don't we try a variable-length StringBufferclass.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325906694&siteId=291194637
Recommended