Theory
JVM Virtual Memory Distribution:
The program counter is the pipeline of the JVM execution program and holds some jump instructions.
The local method stack is the stack used by the JVM to invoke the operating system method.
The virtual machine stack is the stack used by the JVM to execute Java code.
The method area holds some constants, static variables, class information, etc., which can be understood as the storage location of the class file in memory.
The virtual machine heap is the heap used by the JVM to execute Java code.
The constant pool in Java is actually divided into two forms: a static constant pool and a run-time pool .
The so-called static constant pool, the constant pool in the *.class file, is a constant pool in a class file that contains not only string literals, but also classes, methods, and most of the space in the class file. This constant pool is primarily used to hold two major classes of constants: literal (Literal) and Symbolic reference (symbolic References), which is equivalent to the concept of Java language-level constants, such as text strings, such as the constant value declared as final, the symbolic reference is the concept of compilation principles, including the following three types of constants:
- Fully qualified names for classes and interfaces
- Field names and descriptors
- Method name and descriptor
running A constant pool is a JVM virtual machine that, after completing the class mount operation, loads the constant pool in class file into memory and saves it in the method area , which is what we often call a const pool, which refers to the run-time pool in the method area.
Another important feature of running a constant pool with respect to a regular pool of class files is
with Dynamic nature, the Java language does not require constants must only compile time to produce, that is, not pre-placed in the class file of the constant pool content to enter the method area to run the frequent pool, the runtime may also put new constants in the pool, this feature is used by developers more is
intern () of the String classMethod. The Intern () method of string finds whether there is a equal equal string in the constant pool, if any, returns a reference to the string, and if not, adds its own string into the constant pool.
the benefits of a constant pool
Chang is to avoid the frequent creation and destruction of objects and affect the performance of the system, which realizes the sharing of objects.
For example, a string constant pool in which all string literals are placed in a constant pool during the compilation phase.
(1) Save memory Space: All the same string constants in a constant pool are merged, occupying only one space.
(2) Save run Time: when comparing strings, = = is faster than Equals (). For two reference variables, only = = To determine whether the reference is equal, you can also determine whether the actual value is equal.
Next we refer to some examples of the popular constant pools on the web, and then we explain them.
1 String s1 = "Hello"; 2 String s2 = "Hello"; 3 String s3 = "Hel" + "lo"; 4 string s4 = "Hel" + new String ("Lo"); 5 String s5 = new String ("Hello"); 6 String s6 = S5.intern (); 7 String s7 = "H"; 8 String s8 = "Ello"; 9 String S9 = s7 + s8;10 System.out.println (S1 = = s2); True12 System.out.println (S1 = = S3); True13 System.out.println (S1 = = S4); False14 System.out.println (S1 = = S9); False15 System.out.println (S4 = = S5); False16 System.out.println (S1 = = S6); True
First of all, in Java, the direct use of the = = operator, compared to two strings of the reference address, not the comparison content, compare the content please use String.Equals ().
S1 = = S2 This very good understanding, S1, S2 in the assignment, all use the string literal, white point, is to write the string directly to die, during the compilation, this literal will directly into the class file in the constant pool, so as to achieve reuse, loaded into the run-time pool, S1, S2 points to the same memory address, so it is equal.
S1 = = S3 This place has a hole, S3 although the dynamic splicing out of the string, but all the parts involved in the stitching is known literal, during the compilation, this splicing will be optimized, the compiler directly help you spell, so string s3 = "Hel" + "lo"; The class file is optimized to string s3 = "Hello", so S1 = = S3 is established. A new object that is created with a "+" connection between a string object that uses quotation marks to contain text is added to the string pool.
S1 = = S4 Of course not equal, S4 although also splicing out, but the new string ("Lo") this part is not known literal, is an unpredictable part, the compiler will not be optimized, you must wait until run time to determine the results, combined with the string invariant theorem, The ghost knows where the S4 is assigned, so the address must be different. for all "+" connection expressions that contain new objects (including null), the new object is not added to the string pool.
With a schematic diagram to clarify the idea:
S1 = = S9 is not equal, the truth is similar, although S7, S8 in the assignment when the string literal used, but stitching into S9, S7, S8 as two variables, are not predictable, compiler is compiler, it is not possible when the interpreter, can not be determined in the compilation period, so do not optimize, You can only wait for the runtime to create a new string in the heap that is S7, S8, and the address is indeterminate in the heap and cannot be the same as the S1 address in the method area constant pool.
S4 = = S5 have no explanation, absolutely not equal, both are in the heap, but the address is different.
S1 = = S6 The two equals are entirely attributed to the Intern method, S5 in the heap, the content is Hello, the Intern method attempts to add the Hello string to the constant pool and returns its address in the constant pool, because the constant pool already has a Hello string, So the Intern method returns the address directly, whereas S1 points to the constant pool at compile time, so S1 and S6 point to the same address, equal.
Public Static FinalString A = "AB";//constant A Public Static FinalString B = "CD";//constant B Public Static voidMain (string[] args) {String s= A + B;//initializes two constants with A + connectionString t = "ABCD"; if(s = =t) {System.out.println ("s equals t, they are the same object"); } Else{System.out.println ("s are not equal to T, they are not the same object"); }} s equals T, they are the same object
A and B are constants and the values are fixed, so the value of S is also fixed, which is determined when the class is compiled. In other words: String s=a+b; Equivalent to: String s= "AB" + "CD";
Public Static FinalString A;//constant A Public Static FinalString B;//constant BStatic{A= "AB"; B= "CD"; } Public Static voidMain (string[] args) {//initializes two constants with A + connectionString s = A +B; String T= "ABCD"; if(s = =t) {System.out.println ("s equals t, they are the same object"); } Else{System.out.println ("s are not equal to T, they are not the same object"); }} s are not equal to T, they are not the same object
A and B are defined as constants, but they are not immediately assigned. It is a variable when they are assigned and what value they are given before the value of S is calculated. So A and B are similar in nature to a variable before being assigned. Then s cannot be determined at compile time and can only be created at runtime.
At this point, we can draw three very important conclusions:
You must focus on the behavior of the compilation period to better understand the constant pool.
Constants in the run-time pool are basically derived from constant pools in each class file.
When the program runs, the JVM does not automatically add constants to the constant pool unless constants are manually added to the constant pool (such as calling the Intern method).
The above mentioned only refers to the string constant pool, in fact there is an integer constant pool, floating-point type Chang (the basic type of Java wrapper class most of the implementation of the constant pool technology, that is, Byte,short,integer,long,character,boolean; two types of floating-point type of wrapper class float,double does not implement constant pool technology) and so on, but all the same, but a constant pool of numeric types can not manually add constants, the program starts constant in the pool is determined, such as the constant range in the integer constant pool: -128~ 127, (Byte,short,integer,long,character,boolean) These 5 wrapper classes create the corresponding type of cache data for the value [-128,127] by default, but beyond this range you will still be creating new objects.
For example, when auto-boxing, when int is changed to an integer, there is a rule, when the value of your int in -128-integercache.high (127), the return is not a new the integer object, but a cache in the heap In the integer object, (as we can understand, the system has cached an integer from 128 to 127 into an integer array, if you want to turn an int into an integer object, first go to the cache and find the words to return the references directly to you.) , you do not have to new one), and if you are not in -128-integercache.high (127), a new integer object is returned.
Practice
Having said so many theories, let's touch the real constant pool.
As mentioned earlier, there is a static constant pool in the class file, which is generated by the compiler to store the literal in the Java source file (this article focuses only on the literal), assuming we have the following Java code:
1 String s = "HI";
For the sake of convenience, it is so simple, yes! After compiling the code into a class file, open the class file in binary format with Winhex.
Briefly explain the structure of the class file, the first 4 bytes is the class file magic number, to identify this is a class file, white session point is the file header, both: CA FE BA be.
Followed by 4 bytes is the Java version number, here the version number is 34, because the author is compiled with JDK8, the version number and the JDK version of the high and low relative to the higher version can be compatible with the lower version, but the lower version cannot perform a high version. So, if one day the reader wants to know what the JDK version of someone else's class file is compiled with, you can look at these 4 bytes.
Next is the constant pool entrance, the entrance with 2 bytes to identify the constant pool constant number, in this case the value is 1 A, translated into decimal is 26, that is 25 constants, where the No. 0 constant is a special value, so there are only 25 constants.
Constant pools hold various types of constants, they all have their own type, and all have their own storage specifications, this article focuses only on string constants, string constants starting with 01 (1 bytes), and then using 2 bytes to record the length of a string, and then the actual contents of the string. In this case: 01 00 02 68 69.
The next thing to say about running a constant-time pool, because the run-time pool is in the method area, we can set the method area size by JVM parameters:-xx:permsize,-xx:maxpermsize, which indirectly limits the constant pool size.
Assume that the JVM startup parameter is:-xx:permsize=2m-xx:maxpermsize=2m, and then run the following code:
1//Hold reference to prevent automatic garbage collection 2 list<string> List = new Arraylist<string> (); 3 4 int i = 0;5 6 while (true) {7 /// Manually add constant 8 List.add (string.valueof (i++) to the constant pool by using the Intern method . Intern ()); 9}
The program immediately throws: Exception in thread "main" Java.lang.outOfMemoryError:PermGen space exception. PermGen space is the method area, sufficient to illustrate the Chang in the method area.
In Jdk8, the method area is removed and replaced with the Metaspace region, so we need to use the new JVM parameter:-xx:maxmetaspacesize=2m, which is still running as above code, throws: Java.lang.OutOfMemoryError: Metaspace exception. Similarly, the run-time constant pool is divided in the Metaspace area. For specific information about Metaspace area, please search by yourself.
References:deep understanding of Java Virtual Machines ——— JVM advanced features and best practices
In layman's Java constant pool