The Java Virtual machine works in detail, after the Java Virtual machine started the first thing to do memory allocation, the second thing to run the Java program management scheduling. Just like designing a system, the first step is to plan the database or the data structure, and then start the specific business management. The memory allocation of the Java virtual device is mainly divided into heap and stack, the global is the heap, the local is the stack. The noun is Java stack, PC counter, Native stack, Java heap, method common, run constant pool. Java loader features, from the bottom up to check whether the class has been loaded, from the top down to try to load the class.
First, class loader
First, take a look at the Java program's execution process.
From this block diagram it is easy to understand in general how Java programs work. First, you write the Java code and save it to your hard drive. Then you enter it in the command line
Javac Yourclassname.java
At this point, your Java code is compiled into a bytecode (. Class). If you are in the Eclipse IDE or other development tools, and you save the Code, the development tools have done the above compilation, so you can see the class file in the corresponding directory. The class file is still saved to the hard disk, so when you run it on the command line
Java yourclassname
Completed the work in the red box above. The JRE's loader reads the class file from the hard disk and loads the system into the memory area allocated to the JVM-the runtime data areas. Then the execution engine interprets or compiles the class file, translates it into a specific CPU machine code, and the CPU executes the machine code, thus completing the process.
The next step is to focus on what exactly is a classloader? And how does it work?
First look at some of the features of the loader, a bit abstract, but always helpful.
"Hierarchical structure
The ClassLoader is organized into a hierarchical relationship, that is, a parent-child relationship. Among them, Bootstrap is the father of all ClassLoader. As shown in the following:
--bootstrap class Loader:
When running a Java virtual machine, this classloader is created, which loads some basic Java APIs, including the object class. It is important to note that this ClassLoader is not written in the Java language, but is written in C + +.
--extension class Loader:
This loader loads some extension classes outside of the base API, including some classes related to security performance. (The current understanding is not very deep, can only be said in general, later detailed description)
--system Class Loader:
It loads the classes in the application, that is, the classes that are configured in your classpath.
--user-defined Class Loader:
This is the developer's custom loader that extends the definition of the ClassLoader class, loading some of the programmer-defined classes.
"Delegation Mode"
Looking closely at the hierarchy above, when the JVM loads a class, the lower loader will delegate the task to the previous class loader, and the previous load checks to see if it has loaded the class in its namespace, and if it is already loaded, use it directly. If it is not loaded, continue to the top of the delegate. After the check is done, load in reverse order, and if the bootstrap loader cannot find the class, then delegate down until the class file is found. For a particular classloader, a Java class can only be loaded once, meaning that in a Java virtual machine, the complete identity of the class is (Classloader,package,classname). A ray can be loaded by a different class loader.
Give a concrete example to illustrate, now join I have a own definition of the class MyClass need to load, if not specified, the General Delivery app (System) loaded. After receiving the task, the system checks to see if the class is already in its own library, finds that it has not been delegated to extension,extension to perform the same checks, and finds that the topmost boots found no one in the library, so it is based on its path (Java Core class library, such as Java.lang, try to load, did not find this maclass class, so had to (others optimistic about you, to you to complete, you can do nothing, had to give others) down to the extension,extension to their own path (java_home/ Jre/lib/ext) is to find, or not find, continue down, at this time the system loader to the Classpath path to find, found, and then loaded into the Java virtual machine.
Now suppose we put this class in the path of java_home/jre/lib/ext (equivalent to the extension loader), follow the same rules, and finally load the MyClass class by the extension loader, see, Unified types are loaded into the JVM two times, but each time it is done by a different classloader.
"The visibility limits of
The lower loader can see the class in the upper loader, and vice versa, that is, the delegate can only be from bottom to top.
"Does not allow unloading of classes
The class loader can load a class, but it cannot unload a class. However, the ClassLoader can be deleted or created.
After the class has finished loading, the JVM continues to do other work as follows:
The steps in the block diagram are briefly described below:
Loading: The class load described earlier in the article loads the class file in the file system into the JVM memory (running data region)
Verifying: Check that the loaded class file conforms to the Java specification and the virtual machine specification.
Preparing: Allocates the required memory for this class, determines the data structure required for the class's properties, methods, and so on. (Prepare a data structure that assigns the memory required by classes and indicates the fields, methods, and Interfaces de Fined in the class.)
Resolving: Changes the symbol reference in the constant pool to a direct reference. (Not very understanding)
Initialing: Initializes a local variable of the class, assigns a value to the static domain, and executes the static initialization block.
So, what exactly did class loader do when it loaded the class?
To understand the details of this, you must first detail the running data area.
Second, the operating data area
Runtime Data areas: When running a JVM example, the system assigns it a chunk of memory (the size of the memory area can be set), which is managed by the JVM itself. A chunk from this piece of memory is used to store some running data, such as objects created, parameters passed to methods, local variables, return values, and so on. This piece of work is called the Run data area. The run data area can be divided into 6 chunks: Java stack, program count Register (PC register), local method Stack (Native methods stack), Java heap, method area, run Chang (runtime Constant Pool). Running a constant pool should belong to the method area, but because of its importance, the JVM specification is independent of its description. Of these, the previous 3 regions (PC Registers, Java stacks, local method stacks) are owned by each thread on its own, and the latter three are common to all threads in the entire JVM instance. These six chunks are as follows:
"PC Counter:
Each thread has a PC counter, and when the thread starts (start), the PC counter is created, which holds the address of the bytecode instruction (JVM directive) currently being executed.
"Java stack:
Similarly, the Java stack is owned separately by each thread and created when the thread starts. This stack holds a series of stack frames, which the JVM can only do with push and eject (POP) stack frames. Whenever a method is called, the JVM presses a stack frame into the stack, and the stack frame pops up when the method finishes returning. If an exception occurs when the method executes, you can call Printstacktrace and other methods to view the stack. Stack is as follows:
Ok. Now let's take a closer look at what's going on in each stack frame. It is easy to see that each stack frame contains three parts: a local variable array, an operand stack, and a Chang reference to the class to which the method belongs.
Local (local) array of variables:
The local (local) variable array, starting from 0, stores the reference to the object to which the method belongs, the arguments passed to the method, and the local variables. As an example:
public void dosomething (int A, double b, Object o) {...}
The contents of the local variables stored in the stack frame of this method are:
0:this1:a2,3:b4:0
Look carefully, where a double type of B requires two consecutive indexes. When the value is taken, the value in this index is taken out of 2. In the case of a static method, the No. 0 array does not hold the this reference, but instead stores the passed arguments directly.
"Operand stack:
Some of the intermediate variables in the operand stack where the method executes, and the JVM presses or pops the variables as it executes the method. In fact, the operand stack is where the method really works, and when the method is executed, the local variable array and the operand stack are exchanged for data based on the method definition. For example, when you execute the following code, the operand stack is as follows:
int a = 90;int b = 10;int C = a + B;
Note In this diagram, the point of the operand stack is on top, so the first 100 bits are pushed above. As you can see, the operand stack is actually a temporary storage area of data, storing some intermediate variables, the method ends, and the operand stack is gone.
"Stack frame Data reference:
In addition to the local variable array and the operand stack, the stack frame requires a reference to a constant pool. This reference is used to access the constant pool when the JVM executes to data that requires a constant pool. The data in the stack frame is also responsible for handling the return and exception of the method. If returned by return, the stack frame of the method is ejected from the Java stack. If the method has a return value, the return value is pressed into the operand stack of the method that called the method. In addition, a reference to the possible exception table for the method is also saved in the data area. The following example illustrates:
Class example3c{public static void Addandprint () {Double result = Addtwotypes (1,88.88); SYSTEM.OUT.PRINTLN (result); } public static double addtwotypes (int i, double d) {return i+d; }}
When executing the above code, the Java stack looks like this:
Take some time to study it well. It is important to note that the bottom of the stack is above, the stack frame of the Addandprint method is first placed, and then pressed into the stack frame of the Addtwotypes method. The rightmost text indicates that there is an error, and that the addtwotypes execution result is stored in the Addandprint's operand stack.
"Local Method Stack
When a program calls local methods (such as C or C + + code) through JNI (Java Native Interface), the corresponding stack is established based on the language type of the local method.
"Method Area
The method area is shared by all the threads in a JVM instance, and the method area is created when a JVM instance is started. It is used to store run-and-drop constant pools, information about fields and methods, and bytecode for static variables, classes, and methods. Different implementations of the JVM differ in how the method area is implemented. The hotspot of Oracle is called the Permanent Zone (Permanent area) or the permanent generation (Permanent Generation).
"Run a constant pool
This area holds constants for classes and interfaces, and in addition, it holds all references to methods and fields. When a method or domain is referenced, the JVM finds the actual address of the method and domain in memory by running these references in the constant pool.
(heap)
The heap contains objects or instances that are created by the program. This area has a significant impact on the performance of the JVM. The garbage collection mechanism deals with this area of memory.
Therefore, the ClassLoader loading is actually based on the compiled class file, the Java bytecode loaded into the JVM memory, and complete the operation of the data in the initialization work for execution engine execution.
Iii. execution engine (execution engines)
After the ClassLoader loads the bytecode into memory, the execution engine reads the Java bytecode with the Java bytecode directive as a wish. The problem is that now the Java bytecode machine is not readable, so you must also find ways to convert the bytecode into platform-related machine code. This process can be performed by an interpreter, or it can be done with an instant compiler (JIT Compiler).
How Java Virtual machines work