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
new
Objects 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
- Before the
jdk1.7.0
version, theString
constant pool was located in the method area (Method Area) in the memory allocation area of the Java virtual machine . - After the
jdk1.7.0
version, theString
constant pool was moved to heap memory.
For a String
string 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 String
constant pool, if it is passed through new
If a keyword is created, it will be saved in the heap, and new
a few will be saved.
When using new
keywords to create a string, it will first go to the String
constant pool to check whether there is a string with the same content. If it does not exist, it will String
also 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 new
way to go to the String
constant 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 new
operating, 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 String
to 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 StringBuilder
the 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 StringBuilder
object 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 StringBuilder
objects will be created, which is a serious waste of resources.
So why don't we try a variable-length StringBuffer
class.