The memory model of the JVM runtime data area consists of five parts:
"1" Method area
"2" heap
"3" Java stack
"4" PC register
"5" Local method stack
for string s = "haha", it's virtual machine directive:
0:LDC #16; String haha
2:astore_1
3:return
For the above virtual machine directives, their respective instruction flows are described in the Deep Java Virtual machine (combined with the above example):
LDC Directive format: Ldc,index
LDC instruction Process:
To perform the LDC Directive, the JVM first looks for the constant pool entry specified by index, and at the constant pool entry that index points to, the JVM will look for Constant_integer_info,constant_float_info and constant_string _info entrance. If these portals do not yet appear, the JVM resolves them. For the above HAHAJVM, the Constant_string_info entry will be found, and a reference to the detained String object (generated by the process parsing the portal) will be pressed into the operand stack.
Astore_1 instruction Format: astore_1
Astore_1 instruction Process:
To execute the astore_1 instruction, the JVM pops a reference type or ReturnAddress type value from the top of the operand stack, and then deposits the value into the local variable specified by index 1, and the reference type or ReturnAddress type value into the local variable 1.
The process of the return instruction:
Returned from the method, the return value is void.
To talk about my personal understanding:
From the implementation of the LDC directive above, it can be concluded that the value of S is from a reference to the detained string object (generated by the process that parses the portal), which can be understood to be copied from the reference of the detained string object, so the personal understanding is that the value of S is present in the stack. The above is for s worth of analysis, then for the "haha" value of the analysis, we know that for string s = "haha" where the "haha" value in the Java Program compilation period is determined. Simply put, the value of haha is generated in the class file after the program has been compiled into a class file (you can see this haha value in the bytecode file after you open the class file with your UE editor or other text editing tools). In the process of executing a Java program, the first step is to generate the class file and then be loaded by the JVM into memory execution. So the JVM loads this class into memory, where does the haha value, in memory, open up space and store it in what area?
In this case, let's take a look at the structure of the JVM constant pool, which is described in the "Deep Java Virtual Machine" book:
Constant pool
The virtual machine must maintain a constant pool for each mounted type. A constant pool is an ordered set of constants used by that type, including direct constants (String,integer and floating point constants), and symbolic references to other types, fields, and methods. For a string constant, its value is in a constant pool. The Chang in the JVM exists as a table in memory, and for string types there is a fixed-length constant_string_info table for storing literal string values, note that the table stores only literal string values and does not store symbol references. In this case, there should be a clearer understanding of where the string values in the constant pool should be stored.
After introducing the concept of the JVM constant pool, we go on to the location of the memory distribution where the value of "haha" is mentioned. For the value of Haha, the JVM is already haha the string in the constant pool until the class file is loaded into memory by the JVM and the engine parses the LDC Directive and executes the LDC Directive constant_string_ The info table allocates space to store the value of haha. Since haha this string constant is stored in a constant pool, as described in the Deep Java Virtual Machine book, the constant pool is part of the type information, and the type information is each of the types that are reproduced, which is reflected in the JVM memory model that corresponds to the method area that exists in the JVM memory model. That is, the constant pool concept in this type of information is present in the method area, and the method area is allocated by the JVM in the heap in the JVM memory model. Therefore, the value of haha should be present in the heap space.
And for string s = new string ("haha"), its JVM directive:
0:new #16; Class String
3:dup
4:LDC #18; String haha
6:invokespecial #20; Method java/lang/string. "":( ljava/lang/string;) V
9:astore_1
10:return
For the above virtual machine directives, their respective instruction flows are described in the Deep Java Virtual machine (combined with the above example):
New instruction format: New Indexbyte1,indexbyte2
New Instruction Procedure:
To execute the new instruction, the JVM generates an unsigned 16-bit index to the constant pool by computing (INDEXTYPE1<<8) |indextype2. The JVM then looks for a constant pool entry based on the computed index. The constant pool entry that the index points to must be constant_class_info. If the entry does not already exist, the JVM resolves the constant pool entry, which must be a class. The JVM allocates large enough space from the heap for the new object image and sets the instance variable of the object to the default value. Finally, the JVM will point to the new object's reference objectref into the operand stack.
DUP instruction format: DUP
DUP instruction Process:
To execute the DUP instruction, the JVM replicates the contents of the top of the operand stack with a word length, and then presses the copied content into the stack. This instruction can copy the value of any unit word length from the top of the operand stack. But never use it to copy a word length in any two word lengths (long or double) at the top of the operand stack. In the example above, where the reference objectref is copied, there are 2 references in the operand stack.
LDC Directive format: Ldc,index
LDC instruction Process:
To perform the LDC Directive, the JVM first looks for the constant pool entry specified by index, and at the constant pool entry that index points to, the JVM will look for Constant_integer_info,constant_float_info and constant_string _info entrance. If these portals do not yet appear, the JVM resolves them. For the above HAHA,JVM, the Constant_string_info entry will be found, and a reference to the detained String object (generated by the process parsing the portal) will be pressed into the operand stack.
Invokespecial instruction Format: invokespecial,indextype1,indextype2
Invokespecial instruction procedure: For this class, the directive is the invocation of the method used to initialize the instance. In view of the length of the instruction, it is possible to refer to the Deep Java Virtual machine described in detail. In the above example, the constructor of the string class is invoked by one of the references, the object instance is initialized, another same reference is pointed to the initialized object instance, and the previous reference pops up the operand stack.
Astore_1 instruction Format: astore_1
Astore_1 instruction Process:
To execute the astore_1 instruction, the JVM pops a reference type or ReturnAddress type value from the top of the operand stack, and then deposits the value into the local variable specified by index 1, and the reference type or ReturnAddress type value into the local variable 1.
The process of the return instruction:
Returned from the method, the return value is void.
To execute the astore_1 instruction, the JVM pops a reference type or ReturnAddress type value from the top of the operand stack, and then deposits the value into the local variable specified by index 1, and the reference type or ReturnAddress type value into the local variable 1.
With the above 6 instructions, you can see that string s = new string ("haha"), the haha in the heap space, and S is in the operand stack.
Above is the analysis and understanding of the memory condition of the s and haha values; that's for string s = new string ("haha"); How many objects are created in the statement?
My understanding: Here "haha" itself is an object in the constant pool, while executing new String () at run time, copy the object from the constant pool into the heap, and give the reference to the object in the heap to S hold. So this statement creates 2 string objects.
Here are some string-related FAQs:
Final usage and understanding in string
Final StringBuffer a = new StringBuffer ("111");
Final StringBuffer B = new StringBuffer ("222");
a=b;//This sentence compilation does not pass
Final StringBuffer a = new StringBuffer ("111");
A.append ("222");//Compile Through
As you can see, final is valid only for the reference "value" (that is, the memory address), which forces the reference to point only to the object that was initially pointed to, and changes its point to cause a compile-time error. Final is not responsible for the change in the object it points to.
Several examples of String constant pool problems
Here are a few common examples of comparative analysis and understanding:
[1]
String a = "A1";
String B = "a" + 1;
System.out.println ((A = = b)); result = True
String a = "atrue";
String B = "a" + "true";
System.out.println ((A = = b)); result = True
String a = "a3.4";
String B = "a" + 3.4;
System.out.println ((A = = b)); result = True
Analysis: JVM for string constant "+" number connection, the program compile period, the JVM will be the constant string "+" connection optimization to the concatenated value, take "a" + 1, the compiler is optimized in class is already A1. The value of its string constants is determined at compile time, so the final result of the above program is true.
[2]
String a = "AB";
String BB = "B";
String B = "a" + BB;
System.out.println ((A = = b)); result = False
Analysis: JVM for string reference, because in the string "+" connection, there is a string reference exists, and the reference value in the program compilation period is not determined, that is, "a" + BB can not be optimized by the compiler, only during the program run time to dynamically allocate and the new address after the connection to B. So the result of the above program is also false.
[3]
String a = "AB";
Final String bb = "B";
String B = "a" + BB;
System.out.println ((A = = b)); result = True
Analysis: The only difference between [3] is that the BB string has a final decoration, and for a final modified variable, it is parsed at compile time to a local copy of the constant value stored in its own constant pool or embedded in its byte stream. So at this point the "a" + BB and "a" + "B" effect is the same. Therefore, the result of the above program is true.
[4]
String a = "AB";
Final String bb = GETBB ();
String B = "a" + BB;
System.out.println ((A = = b)); result = False
private static String GETBB () {
return "B";
}
Analysis: The JVM for the string reference BB, its value in the compilation period can not be determined, only after the program run time call method, the return value of the method and "a" to dynamically connect and assign the address to B, so the result of the above program is false.
From the above 4 examples can be obtained:
String s = "a" + "B" + "C";
is equivalent to string s = "abc";
String a = "a";
String B = "B";
String c = "C";
String s = a + B + C;
This is not the same, the end result equals:
StringBuffer temp = new StringBuffer ();
Temp.append (a). Append (b). append (c);
String s = temp.tostring ();
From the above analysis results, it is not difficult to infer that the string using the Join operator (+) inefficiency reason analysis, such as the code:
public class Test {
public static void Main (String args[]) {
String s = null;
for (int i = 0; i <; i++) {
s + = "a";
}
}
}
Every time you do it, you produce a StringBuilder object and then throw it away after append. The next time the loop arrives, it re-generates the StringBuilder object and then append the string so that it loops until the end. If we use the StringBuilder object directly for Append, we can save N-1 time to create and destroy objects. So for applications that want to concatenate strings in a loop, the StringBuffer or Stringbulider objects are generally used for append operations.
The Intern method of the string object is understood and analyzed:
public class Test4 {
private static String a = "AB";
public static void Main (string[] args) {
String S1 = "a";
String s2 = "B";
String s = s1 + s2;
System.out.println (s = = a);//false
System.out.println (s.intern () = = a);//true
}
}
The problem with Java is that it is a constant pool. For the s1+s2 operation, a new object is recreated in the heap, and s holds the contents of the new object in the heap space, so s is not equal to the value of a. When you call the S.intern () method, you can return the address value of s in the constant pool, because the value of a is stored in a constant pool, so the values of s.intern and A are equal
Understanding Java Constant Pools