Introduction
?? This article will introduce the Chang and packing unpacking mechanism, the reason is that the two together introduced, is because many articles on the internet when it comes to Chang, the wrapper class cache mechanism, Java constant pool, mixed together in a discussion, or even completely the two as a whole, for beginners to bring a lot of trouble, I just came over. Also, because the caching of wrapper classes is the same as the idea of a string constant pool, it is easy to confuse, but the implementation is not the same.
First, Chang
Before introducing the constant pool, let's introduce the definitions of constants, literal constants, and symbolic constants.
constants can be divided into literal constants (also known as direct constants) and symbolic constants .
literal constants : Refers to numbers, characters, boolen values, strings, and so on that can be used in a program without having to be pre-defined. Simply put, it is the determination of the value itself. such as 10,2l,2.3f,3.5, "Hello", ' a ', true, false, NULL, and so on.
Symbolic Constants : Refers to the amount of an immutable value in a program that is predefined in a program. such as final int a = 5
;
Constant pool
?? Chang introduced to avoid the frequent creation and destruction of objects and affect system performance, which implements the sharing of objects. This is an implementation of the enjoy meta-mode.
Second, Java constant pool
Java's constant pool can be subdivided into the following three categories:
- Volume pool, compile phase)
- Run a constant pool (also known as a dynamic const pool, run phase)
- String Chang (Global Chang)
1. class file Constant Pool
?? The class file constant pool, also known as a static constant pool , is a piece of information contained in a. class file. Used to hold various literal (Literal) and symbolic references (symbolic References) generated by the compiler.
Chang location of the. class file
literal : That is the literal constant above.
symbol Reference : is a set of symbols to describe the referenced target, the symbol can be any form of literal, as long as the use can be used to locate the target without ambiguity (it is distinguished from the direct reference, the direct reference is usually a local pointer to the method area, Relative offset or a handle that can be positioned indirectly to the target). a symbolic reference can be thought of as a virtual address, and a symbolic reference is replaced by a direct reference only if the JVM finishes loading the class and confirms the literal address . The following three types of constants are generally included:
- Fully qualified names for classes and interfaces
- Name and descriptor of the field
- The name and descriptor of the method
Information for constant pools
2. Run a constant-rate pool
?? A run-time pool , also known as a dynamic constant pool, is a JVM that loads the constant pool in the class file into memory and saves it in the method area after it finishes loading classes. In other words, the constants in the run-time pool are basically derived from the constant pool in each class file. Another important feature of running a constant pool relative to a class file's const pool is its dynamic nature, and the Java language does not require constants to be generated only at compile time, which means that the contents of the constant pool in the class file are not pre-placed to enter the method area to run the frequent pool. It is also possible to put new constants into the pool during the run, which is the intern () method of the string class used by developers.
?? When the JVM executes a class, it must be loaded, connected, initialized, and the connection includes validation, preparation, and parsing of three phases. When the class is loaded into memory, theJVM stores the contents of the class constant pool in the run-time pool, which means that each class corresponds to a separate space in the run-time pool where each class file resides . In the parsing phase, the symbolic reference is replaced by the corresponding direct reference.
?? However, literal constants oftype string should be noted: instead of allocating space directly on the heap to create an object, the JVM maintains a constant pool of string constants for string strings. So encountering string constants is to go to the string pool first to find out if there are duplicates, and if so, return the corresponding reference. Otherwise, it is created and added to the string constant pool. In other words, for literal constants of type string, you must maintain a global reference in the string constant pool.
3. String Chang (String pool also known as String literal pool)
?? The string constant pool stores the literal constants of the string. In a bit more detail, the contents of a string constant pool are validated after the class is loaded, a string object instance is generated in the heap after the prep phase, and then the reference value of the string object instance is stored in the string pool (remember: The string pool is a reference value instead of a specific instance object. Specific instance objects are stored in a piece of space that is opened up in the heap. )。
The string pool feature implemented in the Hotspot VM is a stringtable class, which is a hash table that contains a reference to the resident string (which is what we often say in double quotation marks), rather than the string instance itself. That is, after some string instances in the heap are referenced by this stringtable, they are equivalent to being given the identity "resident string". This stringtable is only one instance of each hotspot VM and is shared by all classes.
Difference between running a constant pool and a string const pool
A string constant pool is located in a running constant pool.
?? There are a lot of articles on the Internet that are the same as running a constant pool as a run-time pool. I thought it was the same thing at first. running constant pool and string constant pool before the JDK1.6 of the hotspot, all were placed in the method area, and JDK1.7 moved the string constant pool to the out-of-heap memory. The run-time pool provides a runtime memory space for a constant pool of each class file, whereas a string constant pool maintains a common constant pool of string literals for all class files, that is, when a constant pool of class files is loaded into the run-times pool, The reference to its string literal constant is to be consistent with the maintenance of the string constant pool.
Let's take a few examples to understand the constant pool
@ Example 1? a simple example
public class Test_6 {public static void main(String[] args) { String str = "Hello World!";}}
We use javap-v mytest.class to view the byte code of the class file, which can be JAVAP processed to output information we can read. Such as:
The index #16 location of the class file (the 16th constant pool entry) stores a data structure body that describes the string literal constant information (type, and content index), which is called Constant_string_info. Instead of storing the contents of a string, the struct stores an index that points to the contents of the string-#17, the 17th item stores the binary code of Hello World.
@ Example 2? example of the + operation of string
Let's look at a more complicated example.
public class Test_6 {public static void main(String[] args) { String str_aa = "Love"; String str_bb = "beautiful" + " girl"; String str_cc = str_aa+" China";}}
Also, view the bytecode information for the class file:
?? The constant pool of class files is saved,, Love
beautiful girl
China
, but not Love China
. Why STR_BB and STR_CC are obtained through the + link, why the value of STR_CC does not appear in the constant pool, and the value of STR_BB appears.
?? This is because the value of the STR_BB is computed by two constants, and this constant-only expression is computed by the compiler during compilation, and it is remembered that calculations that can be done by the compiler are not dragged to the runtime to be computed.
?? The STR_CC calculation contains the variable STR_AA, which involves the expression calculation of the variable is calculated during run time, because the variable is unable to determine its value during compilation, especially under multi-thread, and the result is the CPU dynamic allocation space storage, This means that the address is not OK. If we look at it again, we will find that the constant pool contains the StringBuilder
descriptive information of its method, in fact, this StringBuilder
is to calculate str_aa+" China
"expression, first call append()
method, add two string, in Call toString()
method, return result." That is, during the run, the string string is evaluated by a +-linked expression by creating a StringBuilder .
@ Example 3? string New Object Example
?? In the following example, the value of STR_BB is to create a new object directly from new and observe the static constant pool.
public class MyTest {public static void main(String[] args) { String str_bb = new String("Hello");}}
To view the bytecode information for the corresponding class file:
?? The operation of new object through new is done during run time, why is it still present in the constant pool of class file? This is because "Hello" itself is a literal constant, which is very easy to overlook. There are double quotes wrapped in literal constants. At the same time, new creates a string string object that is actually done at run time, but this object will be different from the constant maintained in the string constant pool.
Second, automatic packing and unpacking mechanism and caching mechanism
Let's start with a brief introduction to the automatic packing and unpacking mechanism.
1, automatic loading and unpacking mechanism introduction
Boxing : You can automatically change the base type directly to the corresponding package type.
Unpacking : Automatically converts the package type to the corresponding base type value;
//普通的创建对象方式 Integer a = new Integer(5); //装箱 Integer b = 5; //拆箱 int c = b+5;
2. Principle of automatic packing and unpacking
?? Packing and unpacking is how to realize, feel a bit magical, incredibly can make the basic type and packaging type fast conversion. Let's simplify the above example a little bit more:
public class Test_6 {public static void main(String[] args) { //装箱 Integer b = 5; //拆箱 int c = b+5;}}
Still use javap-v test_6.class to view the bytecode information for class files of this category, such as:
?? The bytecode can be found from the class, static constant pool, Integer.valueOf()
and the Integer.initValue()
description of both methods. This is a bit strange, the code in the example does not call these two methods, why the compilation will appear?
?? The feeling is still not clear enough, we switch to another anti-compilation tool to decompile, this time we decompile back to Java code, using the command Jad Test_6.class, get the following anti-compilation code:
public class Test_6{ public static void main(String args[]) { Integer b = Integer.valueOf(5); int c = b.intValue() + 5; }}
?? This time it is very straightforward. The so-called packing and unpacking is not much, or to be Integer.valueOf()
done by calling (boxing) and Integer.initValue()
(unpacking). That is, the automatic packing and unpacking mechanism is a syntax shorthand, in order to facilitate the programmer, eliminating the hassle of manual packing and unpacking, into the automatic packing and unpacking
Distinguish between packing and unpacking
?? In the following two examples, you may be confused: You do not know whether to use boxing, or to use the unboxing.
Integer x = 1; Integer y = 2; Integer z = x+y;
?? In fact, if you think about it, you can know: This is the first unpacking and packing. Because the integer type is a reference type, you cannot participate in the addition operation, and you must split the box into a basic type to sum it in a boxed integer. If you change the example above and change the integer to short, the correct code is as follows:
Short a = 5; Short b = 6; Short c = (short) (a+b);
3. Caching mechanisms for packaging classes
Let's look at an example first.
public class MyTest { public static void main(String[] args) { Integer a = 5; Integer b = 5; Integer c = 129; Integer d = 129; System.out.println("a==b "+ (a == b)); System.out.println("c==d "+ (c == d)); }}
Operation Result:
A = = B? True
c = = d? false
?? Gee, why is a and B pointing to an object? Does the JVM maintain a constant pool for the wrapper type when the class is loaded? If so, why the address of the variable C and D is different. In fact, the JVM does not maintain a constant pool for the wrapper class. Variables A, B, C, D are from boxing, according to the above, boxing is actually the compiler automatically added a Integer.valueOf()
method. The secret should be within this method, then let's look at Integer.valueOf()
the source code, as follows:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
The code is simple enough to determine whether the base type value used by the boxing is within the range of [ IntegerCache.low
,], and IntegerCache.high
if so, the element corresponding to the subscript in the array is returned IntegerCache.cache
. Otherwise, a new object is created. We continue to look into IntegerCache
the source code as follows:
private static class Integercache {static final int low =-128; static final int high; Static final Integer cache[]; static {//high value is configured by property int h = 127; String Integercachehighpropvalue = Sun.misc.VM.getSavedProperty ("Java.lang.Integer.IntegerCache.high"); Get upper value if (integercachehighpropvalue! = null) {try {int i = Parse Int (Integercachehighpropvalue); i = Math.max (i, 127); Maximum array size is integer.max_value h = math.min (i, Integer.max_value-(-low)-1); } catch (NumberFormatException nfe) {//If The property cannot is parsed into an int, ignore it. }} high = h; Create array cache = new integer[(high-low) + 1]; int j = Low; Fills an array for (int k = 0; K < Cache.length; k++) Cache[k] = new Integer (j + +); range [ -128, 127] must be interned (JLS7 5.1.7) assert Integercache.high >= 127; } private Integercache () {}}
?? From the source, it can be known that IntegerCache.cache
it is a final integer array, which stores the value range of an Integer object element is [-128,127]. and the initialization code for this array is wrapped in a static block of code, which means that the initialization of the IntegerCache.cache
array is done when the class is loaded.
?? Looking back at the example above, the variables A and B use a basic type value of 5, which exceeds the range of [-128,127], so the elements in the cached array are used, so the addresses of a and B are the same. While C, D uses a basic type value of 129, beyond the cache scope, so are each on the heap to create a pair, the address is naturally different.
Wrapper class Cache Summary and supplement:
- The wrapper class is very similar to the String class and is a non-mutable class that cannot be modified once it is created. Because of this feature, the object instances of both are secure under multithreading, without worrying about asynchronous modifications, which provides a good guarantee that they can be shared by simply creating an object share.
- The shared implementation of a wrapper class does not maintain a constant pool by the JVM, but instead uses a caching mechanism (array), which is initialized when the class is loaded and can no longer be modified.
- The array cache scope of the wrapper class is limited, and only the base type value is cached within a byte range, that is, 128 to 127. (The range of character is 0~127)
- Currently not all wrapper classes provide a caching mechanism, only byte, Character, short, Integer 4 wrapper classes are provided, Long, Float, Double is not provided.
Source: http://www.cnblogs.com/jinggod/p/8425748.html
The article is inappropriate, please correct me, you can also pay attention to my public number: 好好学java
, access to high-quality resources.
Java Fundamentals (eight) deep parsing of constant pool and unpacking mechanism