In short, a Java program needs to edit the source code, compile the class file, load the class file, interpret or compile the bytecode instruction in the run class.
Here is a simple Java source code, through it to look at the Java program running process:
1 class Person2 3 {4 5 PrivateString name;6 7 Private intAge ;8 9 Ten One PublicPerson (intAge , String name) { A - This. Age =Age ; - the This. Name =name; - - } - + Public voidrun () { - + A at } - - } - - - in Interfaceistudyable - to { + - Public intStudyintAintb); the * } $ Panax Notoginseng Public classStudentextendsPersonImplementsistudyable - the { + A Private Static intCnt=5; the + Static{ - $cnt++; $ - } - the PrivateString SID; - Wuyi PublicStudent (intAge , string name, String sid) { the - Super(age,name); Wu - This. Sid =SID; About $ } - - Public voidrun () { - ASystem.out.println ("Run () ..."); + the } - $ Public intStudyintAintb) { the the intc = 10; the the intD = 20; - in returna+b*c-D; the the } About the Public Static intgetcnt () { the the returnCNT; + - } the Bayi Public Static voidMain (string[] args) { the theStudent s =NewStudent ("DQRCSC", "20150723")); - -S.study (5,6); the the student.getcnt (); the the S.run (); - the } the the}
1. Edit the Source: whether it is using Notepad or something else, write the above code, and then save to Student.java, I put it directly on the desktop
2. Compile the generated class bytecode file:
On the desktop, hold down SHIFT, and then press the right mouse button:
Click "Open Command Window Here"
Enter the command Javac Student.java compile the source file to generate a. class bytecode file.
Since two classes and one interface are defined in the source file, 3. clsss files are generated:
This allows the bytecode file to run on the Java Virtual machine to generate a
3. Start the Java Virtual machine run bytecode file:
Entering the Java Student command at the command line launches a Java Virtual machine, loads the Student.class bytecode file into memory, and then runs the bytecode instruction in memory.
We've only entered two commands from the compile to the Java program, and even if you're using an integrated development environment such as Eclipse, as long as the ctrl+s is saved for incremental compilation, you just have to press a button to run the Java program. However, there are some actions behind these simple operations ...
1. from source code to bytecode:
Byte-code files, seemingly trivial things, actually implement the Java language cross-platform. The same program storage format is used uniformly by virtual machines of different platforms. Further, the JVM is running a class bytecode file, as long as it is a file of this format, so the JVM is not actually tightly tied to the Java language as I imagined it to be. If you are familiar with the format requirements of bytecode, you can use the binary editor to write one of the required bytecode files and then hand it to the JVM to run it, or compile the source code in other languages into a bytecode file, to the JVM to run, as long as it is a valid bytecode file, the JVM will correctly run up. So, it also implements the cross-language ...
You can view the contents of a. class file directly by Jclasslib, or you can specify parameters for the JAVAP command in the JDK to view information about the. class file:
Javap–v Student
A lot of output, in the Command Line window view is not too convenient, can output redirection under:
Javap–v Student > Student.class.txt
There is an extra Student.class.txt file on the desktop that contains information about the easy-to-read Student.class file.
Part of the class file content, from the above image, You can see that this information comes from Student.class, compiled from Student.java, the main version of the compiler is 52, that is, jdk1.8, the class is public, and then the constant pool that holds the constants in the class, the byte code of each method, etc., is not recorded here.
In short, I would like to say that the bytecode file is very simple and powerful, it holds a variety of information about this class: Fields, methods, parent class, implementation of the interface and other information.
2.Java the basic structure of the virtual machine and its memory partition :
Java Virtual machines Run bytecode instructions, it is necessary to load the bytecode file, who will load, how to load, load to where ... Who will run, how to run, the same should be considered ...
Above is a basic structure of the JVM and memory partition diagram, a bit abstract, a little ugly ... The following is a brief description:
The JVM divides memory into direct memory, method area, Java stack, Java heap, local method stack, PC register, and so on.
Direct Memory : is the original memory area
method Area : Used to store the metadata information of the class, interface, the loaded bytecode data are stored in the method area
Java Stack : run-time memory area where the execution engine runs bytecode, saving call run data for each method in the form of a stack frame
Local method Stack : Runtime memory area when the execution engine calls the local method
java heap : Runtime data area, various objects are generally stored on the heap
PC Register : functions as a PC register in the CPU, indicating the bytecode instruction to execute.
The functional modules of the JVM mainly include the class loader, the execution engine and the garbage collection system .
3. the class loader loads Student.class into memory :
1) The ClassLoader will find the Student.class file in the specified classpath and then read the data in the byte stream and store it in the method area.
2) A class object is created based on the information of Student.class, which is special and usually stored in the method area, and is used as an interface for accessing various data of the student class at run time.
3) necessary verification work, format, semantics, etc.
4) Allocates memory space for static fields in student, also in the method area, and 0 initialization, that is, the numeric type is initialized to 0,boolean to False, the reference type is initialized to null, and so on.
There is only one static field in Student.java:
private static int cnt=5;
At this point, the operation assigned to 5 is not performed, but it is initialized to 0.
5) since it is loaded into memory, the symbolic references to some of the methods, fields, and so on that were stored in the bytecode file can be parsed as direct references in memory, not necessarily until they are actually run.
6) During the compile phase, the compiler collects all the static field assignment statements and static code blocks, and stitching out a class initialization method <clinit> () in the order in which the statements appear. At this point, the execution engine calls this method to initialize the static field with the code written in it.
In Student.java, there are two places for assigning static fields and static code blocks:
1 Private Static int cnt=5; 2 3 Static {45 cnt++; 6 7 }
Will be stitched in the order in which they appear, in the following form:
1 void <clinit>() {23 cnt = 5; 4 5 cnt++; 6 7 }
The bytecode directive for the generated <clinit> () method can be seen through the Jclasslib tool:
The iconst_5 command puts the constant 5 into the stack.
Putstatic #6将栈顶的5赋值给Student. cnt this static field
Getstatic #6 Get the value of student.cnt this static field and put it on top of the stack
Iconst_1 the constant 1 into the stack
Iadd remove two integers from the top of the stack, add the results into the stack
Putstatic #6 take out the integer at the top of the stack and assign it to student.cnt
Return returns from the current method without any return value.
In terms of bytecode, it is true that the two lines of CNT =5 and cnt++ are executed successively.
One thing to note here is that the loading and initialization of the next class is generally described, but, in practice, it is possible to simply load the class without initializing it, because there is no access to the class's fields and methods in the program.
In addition, the actual loading process is relatively complex, before a class loads its parent class and its implemented interfaces: the loading process can be viewed through the java–xx:+traceclassloading parameter:
such as: Java-xx:+traceclassloading Student, too much information can be redirected under:
To view the output of the LoadClass.txt file:
You can see that the first load is the Object.class class, and of course, the parent class of all classes.
Until the No. 390 line to see that the part of its definition is loaded, first student implementation of the interface istudyable, then its parent class person, then the student itself, then a startup class loading, and then is to find the main () method, executed.
4. The execution engine finds the main () entry method, which executes the bytecode directive:
To understand how the method works, you need to know a little bit about the Java stack:
In the JVM through the Java stack, save the method call run information, whenever a method is called, according to the method in the bytecode information for the method to create a stack frame, different methods, the size of the stack frame is different. The memory space in the stack frame can also be divided into 3 blocks, each storing different data:
Local Variables Table : The parameters passed in by the caller of the method, and the local variables created in the method body of the method.
Operand stacks: for storing operands and intermediate results of calculations.
Other stack frame information: such as return address, reference to current method, and so on.
Only the stack frame of the currently running method is at the top of the stack, the current method returns the stack frame of the current method, the stack frame of the caller of the current method becomes the top of the stack, and if other methods are called in the method body of the current method, the stack frame is created for the called method and pressed into the top of the stack.
Note: The local variable table and the maximum depth of the operand stack have been determined during compilation and stored in the Code property of the method bytecode.
Simple View Student.main () The running process:
Simply look at the main () method:
1 public static void Main (string[] args) { 2 3 Student s = new Student (All, "DQRCSC", "20150723" ); 5 s.study (5,6); 7 9 10 11 }
The corresponding bytecode, which is easier to understand when compared to the other:
Note the main () method for this few information:
Mximum Stack Depth Specifies that the current method, the main () method, corresponds to the maximum depth of the operand stack in the stack frame, with a current value of 5
The Maximum Local variables Specifies the size of the local variable table in the main () method, currently 2, and two slots for the parameters and local variables of the method.
Code length specifies the length of the code in the main () method.
Starts the simulation of the operation of the bytecode instructions in main ():
To create a stack frame:
The local variable table length is 2,slot0 storage parameter args,slot1 The local variable student s, the maximum operand depth is 5.
New #7指令: Creates a student object in the Java heap and puts its reference value on top of the stack.
DUP instruction: Copy the value of the top of the stack and then put the copied results into the stack.
Bipush 23: The single-byte constant value 23 is put into the stack.
LDC #8: Remove the constant in the constant pool of # # as "DQRCSC" and merge it into the stack.
LDC #9: Take the constants in the constant pool of # 20150723 out and merge them into the stack.
Invokespecial #10: Call the method represented by the constant of # #, which is the student.<init> () method
The <init> () method is a method that the compiler will call the parent class's <init> () statements, construct code blocks, instance field assignment statements, and the statements in the constructed method that you write. Ensure that the <init> () method of the calling parent class is at the very beginning of the constructor statement that you wrote at the end, and that the construct code block and Instance field assignment statements are sequentially integrated into the <init> () method in the order in which they appear.
Note that the maximum operand stack depth of the student.<init> () method is 3, and the local variable table size is 4.
Note: #9这四条指令向栈中添加了4个数据 from DUP to LDC, and the student.<init> () method requires exactly 4 parameters:
1 Public Student (int age , string name, String sid) {23 Super(age,name); 4 5 this. sid = Sid; 6 7 }
Although only 3 parameters are explicitly defined in the definition, and actually implicitly passing in a reference to the current object as the first argument, the four parameters are sequentially this,age,name,sid.
The above 4 instructions just put the values of the four parameters sequentially into the stack, the parameter is passed, and then called the Student.<init> () method, the stack frame of the method is created and merged into the stack. The No. 0 to 4th slot in the local variable table in the stack frame holds the four parameter values in the stack, respectively.
To create a stack frame for the studet.<init> () method:
The bytecode directive in the Student.<init> () method:
ALOAD_0: The reference value at the local variable table slot0 into the stack
Aload_1: The int value at the local variable table slot1 is put into the stack
Aload_2: The reference value at the local variable table Slot2 into the stack
Invokespecial #1: Call the Person.<init> () method, similar to calling the Student.<init> procedure, create a stack frame, store the values of three parameters into a local variable table, etc.
After returning from Person.<init> (), 3 values for the top of the stack for the argument are recycled.
ALOAD_0: The reference value at Slot0 is put into the stack.
Aload_3: The reference value at SLOT3 is put into the stack.
Putfield #2: Assigns the value "20150723" at the top of the current stack to the SID field of the object referenced by 0x2222, and then stacks two values out of the stack.
Return: Returns the caller, the main () method, and the current method stack frame out of the stack.
Back in the main () method, continue with the following bytecode directive:
Astore_1: Assigns the value of the current stack top reference type to the local variable at slot1 and then out of the stack.
Value of the reference type at ALOAD_1:SLOT1 in the stack
Iconst_5: The constant 5 into the stack, the int constant only 0-5 has the corresponding iconst_x instruction
Bipush 6: Put constant 6 into the stack
Invokevirtual #11: Call virtual method Study (), this method is a method in the overridden interface and requires dynamic dispatch, so the invokevirtual directive is used.
To create a stack frame for the study () method:
Maximum stack depth 3, local variable table 5
Java source code for the method:
public int study (int a, int b) {
int c = 10;
int d = 20;
return a+b*c-d;
}
The corresponding byte code:
Notice here, through the Jclasslib tool to view the bytecode command a bit of a problem, and the source of the deviation ...
Instead, use the command javap–v student to view the bytecode instructions for study ():
Bipush 10: Put 10 into the stack
Istore_3:10 of the top of the stack is assigned to the INT local variable at slot3, i.e. C, out of the stack.
Bipush 20: Put 20 into the stack
Istore 4:20 of the top of the stack is paid to the INT local variable at SLOT4, i.e. D, out of the stack.
The above 4 instructions, to complete the assignment of C and D work.
Iload_1, Iload_2, iload_3 These three instructions will slot1, Slot2, slot3 these three local variables into the stack:
Imul: Stack the top two values on the stack, multiplying the results into the stack:
Iadd: Stack two values from the top of the current stack, adding the result into the stack
Iload 4: Place the local variable of type int at SLOT4 into
Isub: Stack top two values out of the stack, subtract the result into the stack:
Ireturn: Returns the value of the top of the current stack to the caller.
Back to the main () method:
Pop instruction to stack the return value of the study () method
Invokestatic #12 Call static method getcnt () does not need to pass any arguments
The pop:getcnt () method has a return value, which is the stack
Aload_1: The reference value at SLOT1 is put into the stack
Invokevirtual #13: Calls the Run () method of the 0x2222 object, overrides the method from the parent class, requires dynamic dispatch, so use the invokevirtual directive
Return:main () returns and the program finishes running.
Above, is a simple program to run the approximate process, just read some of today's understanding, perhaps the wrong place, hope will not laughable ...
Java Supplements 4----A simple Java program running the whole process