Jun 01, 2021 Article blog
The article is reproduced from the public number: Program New Horizons
This article provides a step-by-step in-depth explanation of the storage of string constant pools and memory changes caused when using the intern method.
Highlight: What happens when a string calls the intern method method and then compares strings?
This article is based on
HotSpot
virtual machines.
Let's take a look at the presentation of what we're going to talk about in this article through an interview question image:
String s1 = new String("he") + new String("llo");
String s2 = new String("h") + new String("ello");
String s3 = s1.intern();
String s4 = s2.intern();
System.out.println(s1 == s3);
System.out.println(s1 == s4);
By executing the above code, you will find that the printed results are true. S
o why would an otherwise unequi equal string be equal after the
intern
method has been called?
Let's take a step-by-step look at the underlying implementations.
The functional definition of
intern()
method:
(1) If the current string content exists in the string constant pool (i.e. the equals() method is true, that is, the content is the same), then the reference to this string in the constant pool is returned directly;
(2) If the current string is not in the string constant pool, create a reference in the constant pool and point to the string that already exists in the heap, and then return the reference in the constant pool.
Simply
intern
method is to determine whether the string exists in the string constant pool, and if it does not exist, it is created and the presence is returned.
Implementing the string constant pool feature in
HotSpot
is a
StringTable
class, which is an
Hash
table with a default size length of 1009. O
nly one instance of each
HotSpot
virtual machine is shared by all classes.
String constants consist of one character and are placed on
StringTable
JDK6 and earlier, the string constant pool is placed in
Perm Gen
zone (method zone).
StringTable
is fixed in length and 1009 in length, which can cause
hash
when there are too many
String
strings, resulting in long lists and significant performance degradation.
At this point, all that is placed in the string constant pool is the string constant (literal).
Due to the limited space and fixation of the permanent generation,
JDK6
storage mode can easily result
OutOfMemoryError
JDK7
was working on a permanent generation, the string constant pool was placed in the heap.
At this point, even if the size of the heap is fixed, for applying tuning work, you only need to resize the heap.
In
JDK7
a string constant pool can hold not only string constants, but also references to strings.
That is, a reference to a string in the heap can exist as the value of a constant pool.
After understanding the basic theory above, let's demonstrate the process and classification of string pooling step by step in the form of a combination of graphics.
The following examples are analyzed on the basis of the
JDK8
version.
When we declare a string in double quotes:
String wechat = "程序新视界";
At this point, the strings within the double quotes are stored directly in the string constant pool.
As for the storage structure above, as we mentioned in the previous article, we don't explain much. Let's see what happens if we declare the same string again.
String wechat = "程序新视界";
String wechat1 = "程序新视界";
When
wechat1
is declared in the above code, you will find that the corresponding string already exists in the constant pool, and will not be recreated, but will simply return the corresponding reference to
wechat1
The corresponding structure diagram is as follows:
At this point, if you compare wechat and
wechat
directly with a double equal sign, it must be equal because their references and literal values are the same.
wechat1
The above is the case of direct double quote assignment, so what if the process of creating a string in the form of new? As mentioned in the previous article, there are two scenarios: the corresponding value exists for the constant pool and there is no corresponding value.
String wechat2 = new String("程序新视界");
If there is a corresponding value, an object reference to the
wechat2
variable is created in the heap, and then the object reference is pointed to a constant that already exists in the string constant pool.
Comparing wechat and
wechat
variables directly using double equal signs is certainly not equal at this point, while comparing literal values using the
wechat2
equals
method is equal.
Another scenario is that when created with new, there is no corresponding constant in the string constant pool. T
his situation now creates a string constant in the string constant pool, and then creates a string in the heap that holds a reference to the corresponding string in the constant pool. a
nd return the address of the object in the heap to
wechat2
The final effect map is still as shown above.
At this point, the situation is different if it is not directly assigned to the new string, but by the operation of the plus sign.
String s1 = "程序";
String wechat3 = new String(s1 + "新视界");
The above code s1 is stored in the constant pool, and the value of
wechat3
is that because
JVM
compiles with
StringBuilder
for plus-size splicing, only one
String
object is created in the heap and the corresponding string is not stored in the constant pool.
The situation at this point is already about creating strings in our interview questions.
So, let's pool through the
intern
method and see how the string constant pool changes.
Also take the code above as an example, at this point
wechat
wechat1
wechat2
three variables and
wechat3
directly with double equal sign comparison is certainly not equal.
Next face
wechat3
for
intern
pooling.
String s1 = "程序";
String wechat3 = new String(s1 + "新视界");
wechat3 = wechat3.intern();
You'll find that
wechat
wechat1
variables are equal to the value of
wechat3
Since
wechat
and
wechat1
are actually one, here's a comparison of
wechat
and
wechat3
to analyze the process.
The state of memory before
intern
method is called is as follows (ignore the s1 part):
It is not surprising that their values are not equal in the figure above. T
he code above is used to pool
wechat3
and assign the results of pooling to
wechat3
The memory structure changes as follows:
At this point, the corresponding two values are judged, because the references and literal values are all the same, so they are equal.
We
intern
already know that if there is a corresponding value in the constant pool, the reference is returned directly.
Then there is another situation, that is, the constant pool does not have a corresponding value will be how to deal with it? Let's start with the following code:
String s2 = "关注";
String wechat4 = new String(s2 + "公众号");
wechat4 = wechat4.intern();
As we said before calling intern, a String object is created in the heap, and no copy is stored in the constant pool, as in the chat3 diagram.
At this point, there is no corresponding string in the constant pool, and after the intern method is called, the memory structure is as follows:
After the
intern
method, a reference to the corresponding string in the heap is stored in the constant pool.
As mentioned above, references can be stored in the string constant pool for
JDK7
and beyond.
Note that when the corresponding string does not exist in the string constant pool, the address returned by calling
intern
method is the address in the heap, corresponding to the 0x99 in the figure.
wechat4
original address points to the address in the heap, so it doesn't change.
At this point, if you define a double quote assignment
wechat5
the following code:
String s2 = "关注";
String wechat4 = new String(s2 + "公众号");
wechat4 = wechat4.intern();
String wechat5 = "关注公众号";
System.out.println(wechat4 == wechat5);
When the variable
wechat5
is initialized, it is found that a reference already exists in the string constant pool, and
wechat5
points directly to the reference, i.e.
wechat5
like
wechat4
points to the
String
object in memory.
The focus of this demo example above is on the reference address returned by the
intern
method.
If a corresponding string already exists in the string constant pool, the address of the string constant is returned at this time, and if there is no corresponding string in the constant pool, the reference in the heap is placed in the corresponding position in the constant pool, where the reference to the string in the heap is stored, and
intern
returns a reference to the string in the heap.
Find out the return logic above and look at the original code:
String s1 = new String("he") + new String("llo");
String s2 = new String("h") + new String("ello");
String s3 = s1.intern();
String s4 = s2.intern();
System.out.println(s1 == s3);
System.out.println(s1 == s4);
Where s1 is the address of the string "hello" in the heap, and s2 is the address of another "hello" string in the heap.
When
s1.intern()
where the address of s1 is stored in the constant pool,
s1.intern()
returns the address of s1, so s1-s3 is the same address.
Then perform
s2.intern()
where the hello string already exists in the constant pool, the type is referenced and points to the address of s1, and the address of s1 is returned after execution, assigned to s4, so s1 and s4 also point to the same address, so equal.
Through the deeper analysis above, we must have a deeper understanding of string constants, string constant pools, and
intern
methods.
If the relevant interview questions are analyzed according to this line of thinking, they can basically be answered accurately.
Is this a detailed explanation of
W3Cschool编程狮
lion's intern method about the JVM string constant pool and String?
Related to the introduction, I hope to help you.