1 overview
As we all know, Java supports platform independence, security, and network mobility. The Java platform, which consists of Java virtual machines and Java core classes, provides a unified programming interface for pure Java programs, regardless of the underlying operating system. It is thanks to the Java virtual machine that it claims to be "compiled once, run everywhere" to be protected.
1.1 Java Program Execution flow
The execution of Java programs depends on the compilation environment and the running environment. The source code is transformed into an executable machine code, which is completed by the following process:
The core of Java technology is the Java Virtual machine, because all Java programs run on the virtual machine. Running Java programs requires a combination of Java virtual machines, Java APIs, and Java class files. The Java Virtual Machine instance is responsible for running a Java program. When a Java program is started, a virtual machine instance is born. When the program is finished, the virtual machine instance is also extinct.
The cross-platform nature of Java because it has virtual machines for different platforms.
1.2 Java Virtual machine
The primary task of a Java virtual machine is to load a class file and execute its bytecode. As can be seen, the Java virtual machine contains a class loader, which can load the class file from the program and API, and the Java API only the classes required by the execution of the program are loaded, and the bytecode is executed by the execution engine.
When a Java virtual machine is implemented by software on the host operating system, the Java program interacts with the host by invoking the local method. Java methods are written in the Java language, compiled into bytecode, and stored in class files. The local method is written by c/c++/assembly language, compiled into processor-related machine code, stored in the dynamic link library, the format of each platform is proprietary. So the local method is to contact the Java program and the underlying host operating system connection mode.
Since the Java virtual machine does not know how a class file was created or tampered with, it implements a class file detector to ensure that the type defined in the class file is safe to use. The class file verifier guarantees the robustness of the program with four independent scans:
- Structure check of class file
- Semantic checking of type data
- BYTE code Verification
- Symbol Reference Validation
Java Virtual machines also perform other built-in security operations when executing bytecode, and they are a Java programming language that guarantees the robustness of Java programs as well as the characteristics of Java virtual machines:
- Type-safe Reference conversions
- Structured Memory Access
- Automatic garbage collection
- Array bounds checking
- null reference check
1.3 Java Virtual machine data types
Java Virtual machines perform calculations by certain data types. Data types can be divided into two types: the base type and the reference type, such as:
But the Boolean is a bit special, when the compiler compiles Java source code into bytecode, it uses int or byte to represent a Boolean. In a Java virtual machine, false is represented by 0, and true is represented by all nonzero integers. As with the Java language, the basic types of Java virtual machines have a range of domains that are consistent everywhere, regardless of the host platform, a long is always a 64-bit, twos-complement signed integer in any virtual machine.
For ReturnAddress, this basic type is used to implement the finally clause in a Java program, which the Java programmer cannot use, and whose value points to the opcode of a virtual machine instruction.
2 architecture
In the Java Virtual Machine specification, the behavior of a virtual machine instance is described in terms of subsystems, memory regions, data types, and directives, which together demonstrate the internal architecture of the abstract virtual machine.
2.1 Class file
The Java class file contains all the information about the class or interface. The "basic type" of the class file is as follows:
U1 |
1 bytes, unsigned type |
U2 |
2 bytes, unsigned type |
U4 |
4 bytes, unsigned type |
U8 |
8 bytes, unsigned type |
If you want to know more, Oracle's JVM SE7 gives the official specification: the Java? Virtual Machine Specification
What the class file contains:
Classfile {U4 magic; //MagicNumber: 0xCAFEBABE to determine if the Java class file isU2 minor_version;//Minor version numberU2 major_version;//Major Version numberU2 Constant_pool_count;//Constant Pool SizeCp_info Constant_pool[constant_pool_count-1];//Constant PoolU2 access_flags;//access flags for class and interface hierarchies (obtained by | arithmetic)U2 This_class;//class index (pointer to a class constant in a constant pool)U2 Super_class;//Parent index (pointer to class constant in constant pool)U2 Interfaces_count;//Interface Index CounterU2 Interfaces[interfaces_count];//Interface Index CollectionU2 Fields_count;//number of fields counterField_info Fields[fields_count];//Field table CollectionU2 Methods_count;//Method Quantity CounterMethod_info Methods[methods_count];//Method Table CollectionU2 Attributes_count;//Number of attributesAttribute_info Attributes[attributes_count];//property sheet}
2.2class Loadsubsystem of the device
The class loader subsystem is responsible for locating and loading type information. In fact, Java virtual machines have two kinds of loaders: System loaders and user-defined loaders. The former is part of the Java Virtual Machine implementation, which is part of the Java program.
- Launch class loader (bootstrap class loader): It is used to load Java's core library, which is implemented by native code and does not inherit from Java.lang.ClassLoader.
- Extension class loader (Extensions class loader): It is used to load the Java extension library. The implementation of the Java virtual machine provides an extension library directory. The ClassLoader finds and loads the Java class in this directory.
- Application class loader (Application class loader): It loads Java classes based on the Classpath (CLASSPATH) of the Java application. In general, Java-applied classes are loaded by it. It can be obtained by Classloader.getsystemclassloader ().
In addition to the system-provided class loaders, developers can implement their own class loaders by inheriting the Java.lang.ClassLoader class to meet some special requirements.
The class loader subsystem covers several other components of the Java virtual machine, as well as classes from the Java.lang library. The method defined by ClassLoader provides an interface for the program to access the class loader mechanism. In addition, for each loaded type, the Java virtual machine creates an instance of the Java.lang.Class class for it to represent the type. As with other objects, the user-defined class loader and instances of the class class are placed in the heap in memory, and the type information loaded is in the method area.
In addition to locating and importing binary class files, the class loader subsystem must also be responsible for validating the correctness of the imported classes, allocating and initializing memory for class variables, and parsing symbol references. These actions also need to be performed in the following order:
- Mount (Find and load binary data of type)
- Connect (Perform validation: Ensure the correctness of the imported type; Prepare: Allocate memory for class variables and initialize them to default values; Parse: Converts a symbol reference in a type to a direct reference)
- Initialize (class variable initialized to correct initial value)
2.3 Method Area
In a Java virtual machine, information about the loaded type is stored in memory in a method area. When a virtual machine mounts a type, it uses the class loader to locate the appropriate class file, then reads the class file and transfers it to the virtual machine, and the virtual machine extracts the type information from it and stores it in the method area. The method area can also be collected by the garbage collector because the virtual machine allows the Java program to be dynamically extended through a user-defined class loader.
The following information is stored in the method area:
- Fully qualified name of this type (e.g. fully qualified name Java.lang.Object)
- The fully qualified name of this type of direct superclass
- Whether this type is a class type or an interface type
- This type of access modifier (public, abstract, a subset of final)
- An ordered list of fully qualified names for any direct hyper-interface
- The type of Chang (an ordered collection, including direct constants [string, Integer and floating point constants], and symbolic references to other types, fields, and methods)
- Field information (field name, type, modifier)
- Method information (method name, return type, parameter number and type, modifier)
- All class (static) variables except constants
- A reference to the ClassLoader class (when each type is loaded, the virtual machine must track whether it is loaded by the startup class loader or by the user-defined class loader)
- A reference to the class class (for each loaded type, the virtual machine creates an instance of the Java.lang.Class class for it accordingly.) For example, if you have a reference to an object in the Java.lang.Integer class, you can get a class object that represents the Java.lang.Integer class only by invoking the GetClass () method referenced by the integer object)
2.4 Stacks
All class instances or arrays that the Java program creates at run time (the array is a true object in the Java Virtual Machine) are placed in the same heap. Because the Java Virtual machine instance has only one heap space, all threads will share the heap. It is important to note that the Java Virtual machine has an instruction to allocate objects in the heap, but there is no instruction to free the memory because the virtual machine gives the task to the garbage collector. The Java Virtual Machine specification does not enforce a garbage collector, it only requires that the virtual machine implementation must manage its own heap space "in some way". For example, an implementation may have a fixed-size heap space, when the space is filled, it simply throws OutOfMemory exception, does not consider the problem of recycling garbage objects, but it is compliant.
The Java Virtual Machine specification does not dictate how Java objects are represented in the heap, which determines how the virtual machine's implementation is designed. A possible heap design is as follows:
A handle pool, an object pool. A reference to an object is a local pointer to the handle pool. The benefits of this design benefit the defragmentation of heap fragments, and when moving objects in the object pool, the handle part simply changes the pointer to the new address of the object. The disadvantage is that every time an instance variable accesses an object, it passes through two pointers.
2.5 Java Stack
Whenever a thread is started, the Java Virtual Opportunity assigns it a Java stack. The Java stack consists of many stack frames, and a stack frame contains the state of a Java method call. When a thread calls a Java method, the virtual machine presses a new stack frame into the thread's Java stack, and when the method returns, the stack frame pops out of the Java stack. The Java stack stores the state of a Java method call in a thread-including local variables, parameters, return values, and intermediate results of the operation. The Java Virtual machine has no registers and its instruction set uses the Java stack to store intermediate data. The reason for this design is to keep the instruction set of the Java Virtual machine as compact as possible, while also facilitating the implementation of the Java Virtual machine on a platform with very few common registers. In addition, the stack-based architecture also facilitates code optimization for dynamic compilers and instant compilers that are implemented by some virtual machines at runtime.
2.5.1 Stack Frame
The stack frame consists of a local variable area, an operand stack, and a frame data area. When a virtual machine invokes a Java method, it obtains the size of the local variable and operand stacks of this method from the type information of the corresponding class, and allocates the stack frame memory according to this, then presses into the Java stack.
2.5.1.1 local Variable Area
The local variable area is organized into an array that counts in terms of length, starting at 0. The bytecode instruction uses the data in the index starting at 0. The values of type int, float, reference, and ReturnAddress occupy one item in the array, while the type is byte, and the values of short and char are converted to int values before being deposited into the array, and also occupy one item. But values of type long and double occupy two consecutive entries in the array.
2.5.1.2 operand stacks
As with the local variable area, the operand stack is also organized into an array of word lengths. It is accessed through standard stack operations----stack and stack. Because the program counter cannot be accessed directly by the program instruction, the Java Virtual machine instruction is to get the operand from the operand stack, so it is run based on the stack instead of the register. The virtual machine takes the operand stack as its working area, because most of the instructions will pop up the data from here, perform the operation, and then press the result back to the operand stack.
2.5.1.3 Frame Data area
In addition to the local variable area and the operand stack, the Java stack frame also requires a frame data area to support constant pool parsing, normal method return, and exception distribution mechanisms. Whenever a virtual machines executes an instruction that needs to use the constant pool data, it accesses it through a pointer to a constant pool in the frame data area. In addition to parsing the constant pool, the frame data area also helps the virtual machine handle the normal end of the Java method or abort the exception. If the return is normal, the virtual machine must restore the stack frame of the method that originated the call, including the setting program counter pointing to the next instruction initiating the calling method, and if the method has a return value, the virtual machine needs to press it into the operand stack of the method that originated the call. To handle exception exits during Java method execution, the frame data area also holds a reference to the exception table for this method.
2.6 Program Counters
For a running Java program, each thread has its own program counter. The program counter is also called the PC Register. The program counter can hold either a local pointer or a returnaddress. When a thread executes a Java method, the value of the program counter is always the address of the next executed instruction. The address can be either a local pointer or an offset from the method's byte code relative to the starting instruction of the method. If the thread is executing a local method, the value of the program counter at this point is "undefined".
2.7 Local Method stack
Any local method interface will use some kind of local method stack. When a thread calls a Java method, the virtual opportunity creates a new stack frame and presses it into the Java stack. When it calls the local method, the virtual machine keeps the Java stack intact, no longer pushes the new stack into the thread's Java stack, and the VM simply dynamically connects and invokes the specified local method directly.
Where the method area and heap are shared by all the threads in the virtual machine instance. When a virtual machine loads a class file, it parses the type information from the binary data contained in the class file, and then puts the type information in the method area. When the program is running, the virtual opportunity puts all the objects that the program creates at run time into the heap.
As with other runtime memory areas, the memory area occupied by the local method stack can be dynamically scaled or shrunk as needed.
3 Execution engine
In the Java Virtual Machine specification, the behavior of the execution engine is defined using the instruction set. The designer implementing the execution engine will decide how to execute the bytecode, which can be interpreted, instantly compiled or directly using the instructions on the chip, or they can be mixed.
The execution engine can be understood as an abstract specification, a specific implementation, or a running instance. The abstract specification uses the instruction set to dictate the behavior of the execution engine. Implementations may use a variety of different technologies-including software, hardware, or the combination of tree species technology. The execution engine that is the run-time instance is a thread.
Each thread in a running Java program is an instance of a standalone virtual machine execution engine. From the beginning of the thread's life cycle to the end, it either executes the bytecode or executes the local method.
3.1 Instruction Set
The byte stream of a method is composed of a sequence of instructions for a Java virtual machine. Each instruction contains a single-byte opcode followed by 0 or more operands. The opcode represents the action that needs to be performed; the operand provides the Java Virtual machine with additional information required to execute the opcode. When a virtual machine executes an instruction, it may use the item in the current constant pool, the value in the local variable of the current frame, or the value at the top of the current frame operand stack.
The abstract execution engine executes one byte-code instruction at a time. Each thread (Execution engine instance) of a program running in a Java Virtual machine performs this operation. The execution engine obtains the opcode, and if the opcode has operands, it gets its operands. It executes the action specified by the opcode and the operand followed, and then gets the next opcode. This process of executing the bytecode will persist until the thread completes, either by returning from its initial method or by not catching the thrown exception, which can mark the completion of the threads.
4 Local Method interface
The Java local interface, also known as JNI (Java Native Interface), is intended for portability. The local method interface allows local methods to do the following:
- Passing or returning data
- Manipulating instance variables
- Manipulating class variables or calling class methods
- manipulating arrays
- Lock the object of the heap
- Loading a new class
- Throw exception
- Catch exceptions thrown by local method call Java methods
- Capturing asynchronous exceptions thrown by a virtual machine
- Indicates that a garbage collector object is no longer required
Reference:
"Deep Java Virtual machine"
Understanding the Java Virtual Machine architecture