Touch Java constant Pool
Java constant pool is an enduring topic, but also the interviewer's favorite, the topic is full of patterns, the side dishes have already heard of the constant pool, this time a good summary.
Theory
A piece of cake first. The JVM virtual memory distribution:
The program counter is the JVM executes the procedure the assembly line, holds some jumps the instruction, this is too advanced, the vegetable dish does not understand.
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 and so on, which can be understood as the storage location of class files in memory.
The virtual machine heap is the heap used by the JVM to execute Java code.
A constant pool in Java is actually divided into two forms: a static constant pool and a running regular pool.
The so-called static constant pool, that is, the constant pool in the *.class file, the constant pool in the class file contains not only string (number) literal, but also class, method information, occupy most of the class file space.
While running a regular pool, the JVM virtual machine loads the constant pool in the class file into memory after it completes the class mount operation, and is stored in the method area, which we often refer to as the constant pool of the method area.
We then cite some examples of constant pools that are popular on the web and then 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;
System.out.println (S1 = = s2); True
System.out.println (S1 = = S3); True
System.out.println (S1 = = S4); False
System.out.println (S1 = = S9); False
System.out.println (S4 = = S5); False
System.out.println (S1 = = S6); True
First of all, in Java, the direct use of the = = operator, compared to the two-string reference address, is not a comparison of content, please use String.Equals ().
S1 = = S2 This very good understanding, S1, S2 in the assignment, the use of string literal, white words point, is directly to write the string dead, during the compilation, this literal will be directly placed in the class file of the constant pool, so as to achieve reuse, load the operation of the regular pool, S1, S2 points to the same memory address, so it is equal.
S1 = = S3 This place has a hole, S3 although is the dynamic splicing out the string, but all participate in splicing the part all is the known literal quantity, during compiles, this kind of stitching will be optimized, the compiler directly helps you to spell well, therefore string s3 = "Hel" + "lo"; is optimized in the class file to string s3 = "Hello";, so S1 = = S3 is established.
S1 = = S4 Of course not equal, S4 is also spliced, but the new string ("Lo") is not a known literal, is an unpredictable part, the compiler will not optimize, must wait until the runtime to determine the results, combined with the string invariant theorem, the Devil knows where the S4 is assigned to, So the address is definitely different. With a diagram to clarify the idea:
S1 = = S9 is also not equal, the truth is similar, although S7, S8 in the value of the string literal, but when stitching into S9, S7, S8 as two variables, are unpredictable, compiler after all is compiler, it is not possible to use the interpreter, so do not optimize, wait until the runtime, S7, S8 A new string, the address in the heap is indeterminate and cannot be the same as the S1 address in the method area constant pool.
S4 = = S5 No longer need to explain, absolutely not equal, both in the heap, but the address is different.
S1 = = S6 These two equals are entirely attributable to the Intern method, S5 in the heap, the content is Hello, and the Intern method attempts to add the Hello string to the constant pool and return its address in the constant pool, because there is already a Hello string in the constant pool, So the Intern method returns the address directly, and S1 points to the constant pool at compile time, so S1 and S6 point to the same address, equal.
So far, we can draw three very important conclusions:
You must focus on the behavior of the compilation period to better understand the constant pool.
The constants in the runtime pool are basically derived from the constant pool in each class file.
When the program runs, the JVM does not automatically add constants to the constant pool unless you manually add constants to the constant pool (such as calling the Intern method).
The above refers only to the string constant pool, there are also integer constant pools, floating-point constant pools, and so on, but they are all the same, except that the constant pool of numeric types cannot add constants manually, and constants in the program startup regular pool are determined, such as the range of constants in an integer constant pool: -128~ 127, only this range of numbers can be used to the constant pool.
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 content in the Java source file (this article only focuses on the literal), assuming that we have the following Java code:
1 String s = "HI";
For the sake of convenience, it's that simple, yes. After compiling the code into a class file, open the binary format class file with Winhex. As shown in figure:
A simple explanation of the structure of the class file, the beginning of the 4 bytes is a class file magic number, used to identify this is a class file, the white Word point is the file header, both: CA FE BA be.
Then 4 bytes is the version number of Java, the version number is 34, because the author is compiled with JDK8, version number and JDK version of the high and low version of the corresponding, the upper version can be compatible with the lower versions, but the lower version cannot perform the high version. So, if one day the reader wants to know what JDK version of someone's class file is compiled with, you can look at these 4 bytes.
Next is the constant pool entry, which identifies the constant pool constant by 2 bytes, in this case the number 1 A, translated to Decimal is 26, there are 25 constants, where the No. 0 constant is a special value, so there are only 25 constants.
Constant pools contain various types of constants, all of which have their own types, and all have their own storage specifications, this article focuses on string constants, string constants start with 01 (1 bytes), then 2 bytes to record string lengths, and then the actual contents of the string. This example is: 01 00 02 68 69.
Let's talk about it. Run a regular pool, because the runtime is in the method area, we can set the method area size through JVM parameters:-xx:permsize,-xx:maxpermsize, thereby indirectly restricting the constant pool size.
Suppose the JVM startup parameters are:-xx:permsize=2m-xx:maxpermsize=2m, and then run the following code:
1//Keep reference, 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 a constant pool by the Intern method . Intern ());
9}
The program immediately throws: Exception in thread "main" java.lang.outOfMemoryError:PermGen a space exception. PermGen space is the method area, enough to show that Chang is 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 parameters:-xx:maxmetaspacesize=2m, which still runs as code, throws: Java.lang.OutOfMemoryError: Metaspace exception. In the same vein, the runtime pool is divided into metaspace areas. For specific information on the Metaspace area, please search the reader yourself.
All the code in this article is tested under JDK7 and JDK8, and other versions of the JDK may be slightly different, please explore them yourself.
References: "Deep understanding Java Virtual machines ——— JVM advanced features and best practices" reproduced from: http://www.cnblogs.com/iyangyuan/p/4631696.html
And then the first part of the code, I tested, ran the results as he wrote. After that part of the practice after that a little scrutiny.