1 I am Queen of the Jing King of Zhongshan
Hello, my name is Li Dahammer, and I am an unrivalled actor. I am about to participate in a stage play called The Romance of the Three Kingdoms, directed by Mr. Luo Guanzhong, an old man whose coffin cannot be pressed down.And I, Uncle Liu, who is about to play one of the three leading characters, hey hey, think there's still a little excitement!
According to the script, I was born in a very low age and was laughed as a "mattress vendor", so at first, I grew up like this B:
public class LiuBei { }
However, at the beginning, I would close two hanging younger brothers, so I became:
public class LiuBei { int zhangFei=123;//Zhang Fei Object guanYu=new Object();//For the sake of troubles, Guan Yu would not customize specific classes for them, just int & Object }
After all, it's enough not to pursue military generals like clouds and advisors, too many people are tired of writing too much, and having two and three brothers on the stage is enough.
Of course, as the future Emperor HanZhaoli, I will start with some special skills, not least one of the protagonists, which is really unique:
public void shuaiErZi() {//Fall Son } public void shouMaiRenXin() {//Buyer's heart shuaiErZi(); } public void geiWoShang(){//Give it to me System.out.printf(zhangFei+""); guanYu.toString();//Well, let's just let Shuan and Zhang lose a skill at random. Object class, just toString. }
Well, Mr. Luo Guanzhong, a well-known programmer lying in his coffin and still coding, has written me a detailed (jian) detailed (lou) start setting through his sophisticated code:
public class LiuBei { int zhangFei=123;//Zhang Fei Object guanYu=new Object();//For the sake of troubles, Guan Yu would not customize specific classes for them, just int & Object public void shuaiErZi() {//Fall Son } public void shouMaiRenXin() {//Buyer's heart shuaiErZi(); } public void geiWoShang(){//Give it to me System.out.printf(zhangFei+""); guanYu.toString();//Well, let's just let Shuan and Zhang lose a skill at random. Object class, just toString. } }
Now, let's prepare for the stage show!
2 Beginner's Village
As the stage plays begin and the cameras move forward, let's take a look at the layout of the entire venue (see: JAVA Memory Structure and Memory Management):
First, the largest area is the background of our stage. We call it a heap. All the famous and lucky heroes (objects) of the three countries will gather in the background and prepare for each other.
Then we can see a huge display, called the method area, which is the script of this play, which says:
- Settings/experiences (class information) of heroes and Heroes
- Liu Bei will encounter closures and then fall his son's skills (attributes, methods)
- Under Cao Cao there are Cao Ren Cao Chun Xia Hou brothers and other hanging forces, as well as the skill of a good wife.(properties, methods)
- ....
- Some people are familiar with information (constants)
- For example, now is the end of the Eastern Han Dynasty. Well, for example, the end of the Eastern Han Dynasty is a constant.
- ...
- The well-known setting of a hero (the static variable of a class).
- Liu Bei: Say that the mattress vendors rolled out for Lao Zi and lost their soul!!
- Cao Cao: I didn't mean to kill people in my dream.
- Sun Quan: You can't say nothing about Hefei or about Sun 100,000.
On the stage, we see three spotlights illuminating a corner of the stage, three threads from the perspective of our three main characters, Cao Sun Liu, and then three square inches illuminated by the spotlights, mainly the virtual machine stack and the local method stack, and a small brand called program counter, which marks where the main character is playing the story.
3 Heroes Ask for Origin
After browsing the stage, I have to go to my desktop, although I already know Mr. Lo Guanzhong's tailor-made draft for me before I took the show:
public class LiuBei { int zhangFei=123;//Zhang Fei Object guanYu=new Object();//For the sake of troubles, Guan Yu would not customize specific classes for them, just int & Object public void shuaiErZi() {//Fall Son } public void shouMaiRenXin() {//Buyer's heart shuaiErZi(); } public void geiWoShang(){//Give it to me System.out.printf(zhangFei+""); guanYu.toString();//Well, let's just let Shuan and Zhang lose a skill at random. Object class, just toString. } }
But draft is only draft, formal stage play, you can't use such crude things to perform, not to mention anything else. Looking at the draft, I only know about my two younger brothers, but at the time of performance, I at least know who is playing Close, and who am I playing against?Hu Ge or Hu Jianhua?
So you also need to reprocess the draft to become a real desktop, a process called compilation, in which case the java file is compiled into a class file.
The contents of the class file are not going to be repeated anymore. Details are given in JAVA Class File and Class Loading Mechanism This is visible in the text.We just need to remember a few core elements:
-
Type information includes magic numbers, major and minor version numbers, and so on.
-
A constant pool contains literal and symbol references.
- Each constant in the constant pool is a table. There are 14 table structures after JDK1.7. These 14 common types have their own structure. The structure and meaning of each constant item are listed below.
- Literal quantity can be understood as character text. When other information in the class file is used in character text, it refers to him. For example, in the field table, the text of the name "Guan Yu" is stored in the constant pool.
- Symbol references fall into the following three categories:
- Fully qualified name: the full name of the class, for example: org/xxx/class/testClass
- Simple name: that is, the field or method name without type and parameter modification, for example, the simple name of the method test() is test, and the simple name of the M field is m.
- Descriptor: Descriptors are used to describe the data type of a field, the parameter list of a method (including number, type, and order), and the return value.According to descriptor rules, the basic data type and void type representing no return value are all represented by one uppercase character, while object type is represented by the character L plus the object's fully qualified name
- For example, the descriptor for "viod main(String[] args)" is "([Ljava/lang/String;)V
- For example, "String[][]", will be recorded as "[[Ljava/lang/String"
- "int[]" is recorded as "[I".
-
Fields table collection, records the field information of this class, for example, we Liu Bei have two younger brothers as objects,
- Here we will record the field names of the shutdown. For example, the value of the name of Guan Yu is the reference to the "Guan Yu" constant in the constant pool.
- The record descriptor (record in descriptor_index), which describes the type of this field, is the Object type here, and this value is a reference to the Ljava/lang/Object constant in the constant pool.
- And various modifiers: similar to: Hanshou Tinghou Meironggong Wusheng Scraping Therapy clinical experimenter Ji Hanqiao Handle Guanyu=public transient volatile Object guanYu.
-
A collection of method tables to record method information of this type, such as our Liu Bei method of falling sons and buying hearts.
- Here we will record the name of the method and also refer to the constant pool.
- The record descriptor (recorded in descriptor_index), the descriptor describing this method, where we are void shuaiErZi(), is a reference to the'()V'constant in the constant pool.(Note that V here refers to void and the descriptor does not include the method name)
- And various modifiers: similar to: full-field / effect group / Liu Bei character inherent / fallen son = public volatile static shuaiErZi
- If there is code in the body of the method, there will be a code attribute (a set of reference attribute tables), which contains the length of the description text of the fallen son (attribute length), the maximum depth of the operand stack, and the specific steps of the fallen son (byte code instructions of the code).
To decompose the class file of the public class LiuBei, we use the javap tool javap-c-v-p-l-constants/home/lisheng/IdeaProjects/learning/out/production/learning/com/company/LiuBei.class, which is the compiled stage play script of Liu Bei.
Classfile /home/lisheng/IdeaProjects/learning/out/production/learning/com/company/LiuBei.class Last modified 2019-12-10; size 1018 bytes MD5 checksum 7133ac0c7e83a62e1081db1945bc6cf9 Compiled from "LiuBei.java" public class com.company.LiuBei minor version: 0 //Minor version major version: 52 //Major Version flags: ACC_PUBLIC, ACC_SUPER //Modifiers for the LiuBei class Constant pool: //Constant pool of classes #1 = Methodref #3.#32 // java/lang/Object."<init>":()V //#1 represents the constant pool index, where is a constant of type Methodref. //In the article JAVA Class Files and Class Loading Mechanisms, we know that there are two index fields within the Methodref type, and two constants are referenced.Represents the fully qualified name of the class to which the method belongs and the method descriptor, respectively. //So #3. #32 is #1 = Methodref refers to constants of index=3 and index=32. //We know that #3 is a Class type and refers to #34= java/lang/Object, so #3 is actually a class constant for java/lang/Object.This means that #1 represents a method of the java/lang/Object class. //As we know, #32 is a NameAndType type constant, and we refer to #20=<init>, #21=()V, which together is the method descriptor of the method that #1 stores. //Thus, we have a complete Methodref whose contents record the fully qualified name of the class in which the method resides and the method descriptor. //And so on, let's not go into any more details #2 = Fieldref #15.#33 // com/company/LiuBei.zhangFei:I #3 = Class #34 // java/lang/Object #4 = Fieldref #15.#35 // com/company/LiuBei.guanYu:Ljava/lang/Object; #5 = Methodref #15.#36 // com/company/LiuBei.shuaiErZi:()V #6 = Fieldref #37.#38 // java/lang/System.out:Ljava/io/PrintStream; #7 = Class #39 // java/lang/StringBuilder #8 = Methodref #7.#32 // java/lang/StringBuilder."<init>":()V #9 = Methodref #7.#40 // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; #10 = String #41 // #11 = Methodref #7.#42 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #12 = Methodref #7.#43 // java/lang/StringBuilder.toString:()Ljava/lang/String; #13 = Methodref #44.#45 // java/io/PrintStream.printf:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; #14 = Methodref #3.#43 // java/lang/Object.toString:()Ljava/lang/String; #15 = Class #46 // com/company/LiuBei #16 = Utf8 zhangFei #17 = Utf8 I #18 = Utf8 guanYu #19 = Utf8 Ljava/lang/Object; #20 = Utf8 <init> #21 = Utf8 ()V #22 = Utf8 Code #23 = Utf8 LineNumberTable #24 = Utf8 LocalVariableTable #25 = Utf8 this #26 = Utf8 Lcom/company/LiuBei; #27 = Utf8 shuaiErZi #28 = Utf8 shouMaiRenXin #29 = Utf8 geiWoShang #30 = Utf8 SourceFile #31 = Utf8 LiuBei.java #32 = NameAndType #20:#21 // "<init>":()V #33 = NameAndType #16:#17 // zhangFei:I #34 = Utf8 java/lang/Object #35 = NameAndType #18:#19 // guanYu:Ljava/lang/Object; #36 = NameAndType #27:#21 // shuaiErZi:()V #37 = Class #47 // java/lang/System #38 = NameAndType #48:#49 // out:Ljava/io/PrintStream; #39 = Utf8 java/lang/StringBuilder #40 = NameAndType #50:#51 // append:(I)Ljava/lang/StringBuilder; #41 = Utf8 #42 = NameAndType #50:#52 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #43 = NameAndType #53:#54 // toString:()Ljava/lang/String; #44 = Class #55 // java/io/PrintStream #45 = NameAndType #56:#57 // printf:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; #46 = Utf8 com/company/LiuBei #47 = Utf8 java/lang/System #48 = Utf8 out #49 = Utf8 Ljava/io/PrintStream; #50 = Utf8 append #51 = Utf8 (I)Ljava/lang/StringBuilder; #52 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder; #53 = Utf8 toString #54 = Utf8 ()Ljava/lang/String; #55 = Utf8 java/io/PrintStream #56 = Utf8 printf #57 = Utf8 (Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; { int zhangFei;//Field table, Zhang Fei, name_index refers to #16=zhangFei of the constant pool descriptor: I//descriptor_index points to #17=I of the constant pool, indicating that the type is int flags: java.lang.Object guanYu;//Field table, Guan Yu, name_index refers to #18=guanYu of the constant pool descriptor: Ljava/lang/Object;//descriptor_index points to #19=Ljava/lang/Object for a constant pool; the representation type is an object class flags: public com.company.LiuBei();//Beginning here is the method table, and LiuBei() is the default constructor for the LiuBei class.name_index points to the constant pool LiuBei literal. descriptor: ()V//descriptor_index points to #21 = Utf8 () V of the constant pool flags: ACC_PUBLIC Code://Code property, which stores byte code instructions for the constructor stack=3, locals=1, args_size=1// 0: aload_0 //Load the value of a variable with index 0 from the local variable table, that is, the reference to this, onto the stack 1: invokespecial #1 // Method java/lang/Object."<init>":()V //Out of the stack, invokespecial means calling a method. Which method is called? Call #1 means java/lang/Object. "<init>": () V method initializes object, that is, init() method of object specified by this completes initialization 4: aload_0 //Load the value of the variable with index 0 from the local variable table again, that is, the reference to this, onto the stack 5: bipush 123 //The 123 constant is pushed onto the stack, and when int is -128~127, the JVM uses the bipush directive to push the constant into the operand stack. 7: putfield #2 // Field zhangFei:I // Assign 123 to ZhangngFei //Similarly, a new Object object is executed, then the <init>method of the Object is executed, then assigned to guanyu and returned. 10: aload_0 11: new #3 // class java/lang/Object 14: dup 15: invokespecial #1 // Method java/lang/Object."<init>":()V 18: putfield #4 // Field guanYu:Ljava/lang/Object; 21: return LineNumberTable: //The offset relationship between an instruction and the number of lines of code, where the first number corresponds to the number of lines of code and the second number corresponds to the number before the instruction in the preceding code line 3: 0 line 4: 4 line 5: 10 LocalVariableTable: //Local variable table where start+length indicates the offset of the variable at the beginning and end of its life cycle in byte code //Slot is the slot in the table of local variables (slot reusable), name is the variable name, and Signatur local variable type description Start Length Slot Name Signature 0 22 0 this Lcom/company/LiuBei; //The same is true below, not to be repeated public void shuaiErZi(); descriptor: ()V flags: ACC_PUBLIC Code: stack=0, locals=1, args_size=1 0: return LineNumberTable: line 7: 0 LocalVariableTable: Start Length Slot Name Signature 0 1 0 this Lcom/company/LiuBei; public void shouMaiRenXin(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokevirtual #5 // Method shuaiErZi:()V 4: return LineNumberTable: line 10: 0 line 11: 4 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/company/LiuBei; public void geiWoShang(); descriptor: ()V flags: ACC_PUBLIC Code: stack=3, locals=1, args_size=1 0: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 3: new #7 // class java/lang/StringBuilder 6: dup 7: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V 10: aload_0 11: getfield #2 // Field zhangFei:I 14: invokevirtual #9 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 17: ldc #10 // String 19: invokevirtual #11 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 22: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 25: iconst_0 26: anewarray #3 // class java/lang/Object 29: invokevirtual #13 // Method java/io/PrintStream.printf:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; 32: pop 33: aload_0 34: getfield #4 // Field guanYu:Ljava/lang/Object; 37: invokevirtual #14 // Method java/lang/Object.toString:()Ljava/lang/String; 40: pop 41: return LineNumberTable: line 13: 0 line 14: 33 line 15: 41 LocalVariableTable: Start Length Slot Name Signature 0 42 0 this Lcom/company/LiuBei; } SourceFile: "LiuBei.java"
After reviewing the reverse parsing above, we need to understand the difference between a method table and a Methodref in a constant pool:
- The former contains all method information, including code, while the latter is translated at best and contains only method name + method descriptor + class qualified name.
- Methodref, as its name implies, is just a reference and exists as a parameter of byte code, such as invokespecial #1, #1 is a Methodref.
- So we can see that there is Methodref=com/company/LiuBei.shuaiErZi:()V in the constant pool, but there is no Methodref=com/company/LiuBei.shouMaiRenXin:()V because the shouMaiRenXin method is not called in the code of Liu Bei class, so it does not need a Methodref containing its basic information
- Another popular analogy is that Liu Bei has the skills to buy people's hearts, and the starting step of the buyer's heart skills contains the words "shout out your son's fall" and start his own skills at the same time", so Liu Bei needs to remember the three words"fall your son"like a recipe (that is, he needs to have this ref in the constant pool), because he will not shout out the"buyer's heart"at all.Four-word chance, so there is no need for a ref of the "heart of the buyer" in the constant pool.
4 Rehearse for the World
The content of our desktop (class information) was finally understood above, and I finally understood what the code written by old director Luo Guanzhong really means.The stage show is about to start, so let's rehearse (class loading).
Load
As the first step in rehearsal, do each of our actors always have to get our own desktop?
Loading is the process of importing the contents of a desktop paper (class file) into the large screen of the method area, so that each of us can peek at our settings like a word picker while rehearsing.
Import the contents of all required desktop manuscripts (class files) into the large screen by using the name of a desktop (class) (fully qualified name), using the following methods:
- Currently available from zip packages, which are the basis of jar, ear, war formats.
- Get it from the network, which is the applet implementation.
- Runtime calculation generation, typically dynamic proxy.
- Generated from other files, typically JSP applications, are class classes generated for JSP files.
- It is rare to read from a database.
Generates a java.lang.Class object in memory that represents this class as an access point to various data of this class in the method area.It is not explicitly stored in the heap; in fact, it is an object, but the HotSpot virtual machine still stores it in the method area.
Verification
Verification is to ensure that the information contained in the byte stream of the Class file meets the requirements of the current virtual machine and does not endanger the security of the virtual machine itself. For a three-country stage play, you can't break into a Li Kui.
Validation checks the validation of formats, specifications, references.
Get ready
The content of the desktop we imported is already displayed on the large screen of the method area. We can see some information written above by Liu Bei. Suppose he has a setup for "mat vendor performance" (class variable), that is static String sheDing= "mat vendor performance".So let's put these four words in the spotlight because they are well-known settings (class variables) and the chances of being referenced in a performance are high.(Instance variables do not allocate memory at this time)
So look for a place on the big screen in the method area (allocate memory), but note that only a space is left for it, but the "mat vendor" has not yet been executed Four words are written on it, so it's only the initial value.
These are the initial values for the basic data type
analysis
As we mentioned before, many of the symbolic references stored in the desktop are symbol references (fully qualified name, simple name, descriptor). For example, we only know the names and types of Zhang Fei and Guan Yu, and we don't know which actor they correspond to.
Resolution is the process of referencing symbols on a tablet to correspond to real actors.(Virtual Machine replaces a symbolic reference in a constant pool with a direct reference process)
Let's analyze the process of Liu Bei's analysis:
First, the class loader loads information about the class LiuBei.
Then, according to the desktop, we know that Liu Bei has the skill of "Give Me Up" (the real parsing order is not the same, but here is only an example, the logic is the same).
public void geiWoShang(){//Give it to me System.out.printf(zhangFei+""); guanYu.toString();//Well, let's just let Shuan and Zhang lose a skill at random. Object class, just toString. }
The complete information for the geiWoShang method exists in the method table collection (various modifiers, field types, and field names, as well as various properties are recorded).
Looking at the decompilation information above, we can see that there is a Methodref for the shuaiErZi method in the constant pool. So it is also the method of Liu Bei. Why is there no Methodref for the geiWoShang method in the constant pool?It is important to remember that only the target (method, or field) as a byte code parameter is necessary to place their references in the constant pool.The shuaiErZi method is referenced by the shouMaiRenXin method, so there is a Methodref for the shuaiErZi method.
The method table length is as follows:
public void geiWoShang(); descriptor: ()V flags: ACC_PUBLIC Code: stack=3, locals=1, args_size=1 0: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 3: new #7 // class java/lang/StringBuilder 6: dup 7: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V 10: aload_0 11: getfield #2 // Field zhangFei:I 14: invokevirtual #9 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 17: ldc #10 // String 19: invokevirtual #11 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 22: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 25: iconst_0 26: anewarray #3 // class java/lang/Object 29: invokevirtual #13 // Method java/io/PrintStream.printf:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; 32: pop 33: aload_0 34: getfield #4 // Field guanYu:Ljava/lang/Object; 37: invokevirtual #14 // Method java/lang/Object.toString:()Ljava/lang/String; 40: pop 41: return LineNumberTable: line 13: 0 line 14: 33 line 15: 41 LocalVariableTable: Start Length Slot Name Signature 0 42 0 this Lcom/company/LiuBei;
One of the properties is called code, which is the byte code of the method body code. It looks like this:
... 33: aload_0 34: getfield #4 // Field guanYu:Ljava/lang/Object; 37: invokevirtual #14 // Method java/lang/Object.toString:()Ljava/lang/String; 40: pop ...
Yes, let's ignore the others and just look at the call to guanYu.toString(); as an example.
Getfield #4 means pushing the fourth item of the constant pool onto the stack.OK, item 4 of the constant pool has not been resolved yet, so if we want to resolve the code of the geiWoShang method, we must first resolve item 4 of the constant pool.
What's the fourth item of the constant pool? It's a Fieldref. Yes, it's a Fieldref for the field Guanyu.
This is probably what happens when the structure is abstract:
Fieldref{ Class{ index="com/company/LiuBei";index Pointing to a constant pool #15=com/company/LiuBei;, indicating that the Guanyu field belongs to the LiuBei class. } NameAndType{ name_index="guanYu";//Field table, Guan Yu, refers to #18=guanYu of the constant pool descriptor_index="Ljava/lang/Object";//descriptor_index points to #19=Ljava/lang/Object of the constant pool; indicates that the type of the Guanyu field is the object class } };
Fieldref's lass_info tells us that it belongs to LiuBei, which has already been loaded and is ignored.(Otherwise, it will enter the loading process of other classes, that is, use the loader area of Liu Bei class to load other classes.)
Then the name and descriptor of the field are derived from Fieldref's name_index and descriptor_index, and the field with exactly the same name and descriptor is found in the field table of the LiuBei class to which it belongs.Okay, found:
java.lang.Object guanYu;//Field table, Guan Yu, name_index refers to #18=guanYu of the constant pool descriptor: Ljava/lang/Object;//descriptor_index points to #19=Ljava/lang/Object for a constant pool; the representation type is an object class flags:
Then the offset of the field table of Guan Yu in the Liu Bei class is taken as a direct reference, covering the fourth item of the constant pool, that is, #4=the offset of the field table of Guan Yu in the Liu Bei class. After parsing the field of Guan Yu, make a mark and parse it.
The next time getfield #4 is executed, #4 points directly to a direct reference to the Guanyu field table.
Similarly, let's next parse invokevirtual #14, which represents an example method pointed to by the call #14.
#14 = Methodref length in constant pool
Methodref{ Class{ index="java/lang/Object";index Pointing to a constant pool #3=java/lang/Object;, which means the method is Object's method. } NameAndType{ name_index=" toString";//#53=toString pointing to the constant pool, indicating the name descriptor_index="()Ljava/lang/String";//descriptor_index points to #54=()Ljava/lang/String of a constant pool; representing a method descriptor } }
Similarly, first parse the Object class to which it belongs, oh, loaded as well.
Then, according to the name and descriptor, find the offset of the toString method in the method table of the Object class and assign it to item 14 of the constant pool.
By analogy, the conversion of symbolic references to direct references for all classes is completed.
Initialization
The initialization phase is the process of executing the class constructor <clinit>() method.Assign an initial value to the class variable, in which case the "mat vendor" can assign a value to the space left before.