Java Virtual Machine Architecture

Source: Internet
Author: User

The life cycle of a Java virtual machine

The bounden duty of a runtime Java Virtual machine instance is to be responsible for running a Java program. When a Java program is started, a virtual machine instance is created. When the program shuts down, the virtual machine instance also dies. If you run three Java programs concurrently on the same computer, you will get three instances of the Java virtual machine. Each Java program runs in its own instance of the Java virtual machine.

The Java Virtual machine instance runs a Java program by invoking the main () method of an initial class. and this main () method must be common (public), static, return value void, and accept an array of strings as arguments. Any class that has such a main () method can be used as a starting point for the Java program to run.

Test {    Main (//TODO auto-generated method stub System.  Out.println ("Hello World");}}   

In the example above, the main () method in the initial class of the Java program will be the starting point of the program's initial thread, and any other threads are started by this initial thread.

There are two types of threads inside a Java Virtual machine: The daemon thread and the non-daemon thread. A daemon thread is typically used by a virtual machine, such as a thread that performs garbage collection tasks. However, a Java program can also mark any thread it creates as a daemon thread. The initial thread in the Java program-the one that started with main ()-is a non-daemon thread.

This Java program continues to run as long as any non-daemon threads are running. When all non-daemon threads in the program are terminated, the virtual machine instance automatically exits. If the security Manager allows, the program itself can be exited by invoking the runtime class or the exit () method of the System class.

Architecture of the Java Virtual machine

is a structure diagram of a Java virtual machine, each Java Virtual machine has a class loading subsystem that mounts the type (class or interface) according to the given fully qualified name. Similarly, each Java virtual machine has an execution engine that is responsible for executing instructions that are contained in the methods of the loaded class.

  

When a Java Virtual machine runs a program, it needs memory to store many things, such as bytecode, other information from the loaded class file, objects created by the program, parameters passed to the method, return values, local variables, and so on. Java Virtual machines organize these things into several "runtime data areas" for ease of administration.

Some run-time data areas are shared by all threads in the program, and others are owned by only one thread. Each Java virtual machine instance has a method area and a heap that 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. These types of information are then placed in the method area. When the program is running, the virtual opportunity puts all objects created by the program at run time into the heap.

  

When each new thread is created, it will get its own PC Register (program counter) and a Java stack, and if the thread is executing a Java method (not a local method), then the value of the PC register will always point to the next instruction to be executed. Its Java stack always stores the state of the Java method call in the thread-including its local variables, the arguments that are called simultaneous, the return value, and the intermediate results of the operation. The state of a local method call is stored in a local method stack in a way that relies on a specific implementation, or in a register or some other memory area that is related to a particular implementation.

The Java stack is made up 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 is ejected from the Java stack and discarded.

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, and also to facilitate the implementation of Java virtual machines on platforms that have very few common registers. In addition, this stack-based architecture of Java virtual machines also facilitates the code optimization of dynamic compilers and instant compilers that are implemented by some virtual machines at runtime.

Depicts the memory area created by the Java Virtual machine for each thread, which is private, and no thread can access the PC registers or Java stacks of another thread.

  

Shows a snapshot of a virtual machine instance, which has three threads executing. Thread 1 and thread 2 are executing Java methods, while thread 3 is executing a local method.

The Java stack grows downward, and the top of the stack is displayed at the bottom of the graph. The stack frame of the currently executing method is represented by a light color, and for a thread that is running a Java method, its PC register always points to the next instruction to be executed. For example, thread 1 and thread 2 are all light-colored, because thread 3 is currently executing a local method, so its PC register-the one in dark color, whose value is indeterminate.

Data type

Java virtual machines are computed by certain data types, which can be divided into two types: the base type and the reference type, the basic type of the variable holding the original value, and the reference type's variable holding the reference value.

  

All the basic types in the Java language are also basic types in the Java Virtual machine. But the Boolean is a bit special, although the Java Virtual Machine also regards the Boolean as the basic type, but the instruction set has limited support for Boolean, and when the compiler compiles the Java source code into bytecode, it uses int or byte to represent the Boolean. In a Java virtual machine, false is represented by an integer zero, and all nonzero integers represent true, and operations involving Boolean values use Int. In addition, a Boolean array is accessed as a byte array, but in the heap area, it can also be represented as a bit field.

Java Virtual machines also have a basic type that is only used internally: Returnaddress,java programmers cannot use this type, and this basic type is used to implement the finally clause in a Java program. The type is a JSR, ret, and jsr_w instruction that needs to be used, and its value is a pointer to the opcode of the JVM instruction. The ReturnAddress type is not a numeric value in a simple sense, does not belong to any of the basic types, and its value cannot be modified by a running program.

The reference type of a Java virtual machine is collectively referred to as "reference (Reference)", with three reference types: class type, interface type, and array type, whose values are references to dynamically created objects. A value of a class type is a reference to an instance of a class, and the value of an array type is a reference to an array object, and in a Java virtual machine, it is a real object, and the value of an interface type is a reference to an instance of a class that implements the interface. There is also a special reference value of NULL, which indicates that the reference variable does not reference any object.

Reference passing of method parameters in Java

There are two types of parameters in Java that are passed by value and passed by reference. Pass by value Needless to say, let's say it by reference.

" when an object is passed as a parameter to a method ," This is known as passing by reference.

public     Class user {private String name; public String getName () {return name;} public void setname (String name) {this.name = Name } } 
Test {        Set (user user) {user.setname (main (new user); test.  Set (user); System. out.println (User.getname ());}}     

The output of the above code is "Hello World", which needless to say, if the set method is changed to the following, what will be the result?

Set (user user) {        user.setname ("Hello World");        new User ();        User.setname ("Change");}  

The answer is still "Hello World", let's analyze the code below.

First of all

User user = new user ();

is to create an object in the heap and create a reference in the stack that points to the object, such as:

Test. Set (user);

is to pass the reference user as a parameter to the Set method, note that this is not the reference itself, but a copy of the reference. This means that at this point there are two references (references and referenced copies) pointing to objects in the heap, such as:

User. SetName ("Hello World"); 

In the Set () method, the user object in the "copy of user Reference" action heap, set the string "Hello World" to the Name property. Such as:

  

user = new User ();

In the Set () method, a user object is created and a "copy of user Reference" is pointed to the newly created object in the heap, such as:

  

User. SetName ("Change"); 

In the Set () method, the "Copy of user Reference" operation is the newly created user object in the heap.

The set () method executes and the gaze returns to the Mian () method

System. Out. println (usergetName ());   

Because previously, the "copy of User Reference" has set the Name property of the user object in the heap to "Hello World", so when the user in the main () method calls GetName (), the result is "Hello World". Such as:

  

Class loading Subsystem

In a Java virtual machine, the part that is responsible for locating and loading the type is called the Class mount subsystem.

Java virtual machines have two kinds of loaders: Start the class loader and the user-defined class loader. The former is part of the Java Virtual Machine implementation, which is part of the Java program. Classes loaded by different class loaders are placed in different namespaces inside the virtual machine.

The class loader subsystem covers several other components of the Java virtual machine, as well as several classes from the Java.lang library. For example, a user-defined class loader is a generic Java object whose class must derive from the Java.lang.ClassLoader class. The methods defined in ClassLoader provide an interface for programs 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 all 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 helping to parse symbol references. These actions must be performed in the following order:

(1) Loading--Find and load binary data of type. (2) connection--point to verify, prepare, and parse (optional).

Verify that the type being imported is correct.

You are ready to allocate memory for the class variable and initialize it to the default value.

parsing Converts a symbol reference in a type to a direct reference.

(3) Initialize-initializes the class variable to the correct initial value.

Each Java virtual machine implementation must have a startup class loader that knows how to load a trusted class.

Each class loader has its own namespace, which maintains the type it loads. So a Java program can load multiple types with the same fully qualified name multiple times. A fully qualified name of such a type is insufficient to determine uniqueness in a Java virtual machine. Therefore, when more than one class loader loads a type with the same name, in order to uniquely identify the type, precede the type name with the class loader identity that loads the type that indicates the namespace in which it resides.

Method area

In a Java virtual machine, information about the loaded type is stored in memory that is logically referred to as the method area. When a virtual machine loads a type, it uses the class loader to locate the appropriate class file, and then reads the class file-1 linear binary data streams, which are then transferred to the virtual machine, and then the virtual machine extracts the type information and stores the information in the method area. Class (Static) variables in the type are also stored in the method area.

How the Java Virtual machine stores type information internally is determined by the implementation-specific designer.

When a virtual machine runs a Java program, it looks for type information that is stored in the method area. Because all threads share the method area, their access to the method area data must be designed to be thread-safe. For example, suppose that two threads are attempting to access a class named Lava, and the class has not been loaded into a virtual machine, then there should only be one thread to load it, while the other thread can only wait.

For each mounted type, the virtual machine stores the following types of information in the method area:

The fully qualified name of this type

The fully qualified name of this type of direct superclass (unless the type is java.lang.Object, it has no superclass)

Whether this type is a class type or an interface type

This type of access modifier (a subset of public, abstract, or final)

An ordered list of fully qualified names for any direct hyper-interface

In addition to the basic type information listed above, the virtual machine has to store the following information for each mounted type:

Constant pool of this type

Field information

Method information

All class (static) variables except constants

A reference to the class ClassLoader

A reference to Class

  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 and symbolic references to other types, fields, and methods. The data items in the pool are accessed by the index as if they were arrays. Because a constant pool stores symbolic references to all types, fields, and methods used by the corresponding type, it plays a central role in the dynamic connection of Java programs.

Field information

For each field declared in a type. The following information must be saved in the method area. In addition, the order in which these fields are declared in the class or interface must also be saved.

0 Field names

0 Type of field

0 modifier for field (public, private, protected, static, final, volatile, a subset of transient)

Method information

For each method declared in a type, the following information must be saved in the method area. As with fields, the order in which these methods are declared in a class or interface must also be saved.

0 Method Name

0 return type (or void) of the method

0 number and type of method parameters (in declaration order)

0 modifier for method (public, private, protected, static, final, synchronized, native, a subset of abstract)

In addition to the entries listed in the preceding list, if a method is not abstract and local, it must also hold the following information:

0 byte code of the method (Bytecodes)

0 the size of the local variable area in the stack frame of the operand stack and the method

0 Exception Table

Class (Static) variable

A class variable is shared by all instances of the class, but it can be accessed even if there are no class instances. These variables are only related to classes--not instances of classes, so they are always stored as part of the type information in the method area. In addition to the compile-time constants declared in the class, the virtual machine must allocate space for these class variables in the method area before using a class.

The compile-time constant, which is the class variable initialized with the final declaration and the value that is known at compile times, differs from the usual class-variable processing, and each type that uses a compile constant will copy all its constants into its own constant pool, or embed it in its byte stream. As part of a constant pool or byte stream, the compile-time constant is stored in the method area-just like a generic class variable. However, when generic class variables are saved as part of the data surface of the type that declares them, compile-time constants are saved as part of the type that uses them.

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. If the user-defined class loader is loaded, the virtual machine must store a reference to the loader in the type information. This is saved as part of the type data in the method table.

The virtual opportunity uses this information during a dynamic connection. When a type references another type, the virtual opportunity request loads the class loader that initiates the reference type to mount the referenced type. This dynamic connection process is also critical to how the virtual machine separates namespaces. To be able to properly perform dynamic connections and maintain multiple namespaces, the virtual machine needs to know in the method table which class loader each class is loaded in.

Reference to Class class

For each loaded type (whether it is a class or an interface), the virtual machine creates an instance of the Java.lang.Class class accordingly, and the virtual machine must somehow associate the instance with the type data stored in the method area.

In a Java program, you can get and use a reference to a class object. A static method in class classes allows the user to get a reference to the class instance of any loaded classes.

Class<?> forname (String className)

For example, if you call forname ("Java.lang.Object"), you will get a reference to the class object that represents Java.lang.Object. You can use forname () to get a reference to a class object of any type in any package, as long as the type can be (or has been) loaded into the current namespace. If the virtual machine cannot mount the requested type to the current namespace, the ClassNotFoundException exception is thrown.

Another way to get a class object reference is to call the GetClass () method of any object reference. This method is inherited by all objects from the object class itself:

Class<?> getclass ();

For example, if you have a reference to an object in the Java.lang.Integer class, you can simply call the GetClass () method referenced by the integer object to get a class object that represents the Java.lang.Integer class.

Method Area Usage Instance

To illustrate how the virtual machine uses the information in the method area, here are some examples:

Lava {    Flow() {}} 
Volcano {        mainnew Lava (); Lava.flow ();}} 

Different virtual machine implementations may operate in a completely different way, as described below is just one possibility-but not the only one.

To run the Volcano program, you first have to tell the name of the virtual machine "Volcano" in some "implementation-dependent" way. After that, the virtual machine will find and read the corresponding class file "Volcano.class", and it will extract the type information from the binary data in the imported class file and place it in the method area. By executing the bytecode stored in the method area, the virtual machine starts executing the main () method, and at execution time it holds a pointer to the Chang (a data structure in the method area) of the current class (The Volcano Class).

Note: When the virtual machine starts executing the bytecode of the main () method in the Volcano class, although the lava class is not loaded yet, as with most (perhaps all) virtual machine implementations, it does not wait until all the classes in the program are loaded before it starts to run. On the contrary, it only loads the appropriate class when it is needed.

The first instruction of main () tells the virtual machine to allocate enough memory for the class that columns the first item in the constant pool. So the virtual machine uses a pointer to the volcano constant pool to find the first item, finds it a symbolic reference to the lava class, and then checks the method area to see if the lava class has been loaded.

This symbol reference is simply a string that gives the fully qualified name "Lava" of the class Lava. To enable the virtual machine to find the class from a name as quickly as possible, the designer of the virtual machine should choose the best data structure and algorithm.

When the virtual machine discovers that a class named "Lava" has not been loaded, it begins to find and mount the file "Lava.class" and puts the type information extracted from the read binary data into the method area.

Immediately after that, the virtual machine replaces the first item of the constant pool with a pointer directly to the Lava class data (that is, the string "Lava"), which can be used to quickly access the Lava class. This substitution process is called constant pool resolution, which replaces the symbolic reference in a constant pool with a direct reference.

Finally, the virtual machine is ready to allocate memory for a new lava object. At this point it needs information in the method area. Remember the pointer you just put to the first item in the Volcano class constant pool? Now the virtual machine uses it to access the lava type information and find out how much heap space a lava object needs to allocate.

Java virtual machines can always determine how much memory an object needs by storing the type information of the method area, and when the Java virtual machine determines the size of a lava object, it allocates so much space on the heap and initializes the variable speed of the object instance to the default initial value of 0.

When the reference to the newly generated lava object is pressed onto the stack, the first instruction of the main () method is also completed. The next instruction calls the Java code with this reference (the code initializes the speed variable to the correct initial value of 5). Another instruction will use this reference to invoke the flow () method referenced by the lava object.

Heap

All class instances or arrays that the Java program creates at run time are placed in the same heap. There is only one heap space in a Java virtual machine instance, so all threads will share the heap. And because a Java program has a single Java virtual machine instance, each Java program has its own heap space--they don't interfere with each other. However, multiple threads of the same Java program share the same heap space, in which case the synchronization of multi-threaded access Objects (heap data) is considered.

The Java Virtual machine has a directive that allocates new objects in the heap, but does not have instructions to free up memory, just as you cannot explicitly release an object in the Java code area. The virtual machine itself is responsible for deciding how and when to release memory that is occupied by objects that are no longer referenced by the program being run. Typically, the virtual machine gives this task to the garbage collector.

Internal representation of an array

In Java, an array is a real object. As with other objects, arrays are always stored in the heap. Similarly, arrays have a class instance associated with their class, and all arrays of the same dimension and type are instances of the same class, regardless of the length of the array (the length of each dimension of the multidimensional array). For example, an array containing 3 int integers and an array containing 300 integers have the same class. The length of the array is only relevant to the instance data.

The name of an array class consists of two parts: each dimension is represented by a square bracket "[", and the element type is represented by a character or string. For example, a one-dimensional array whose element type is an int integer has the class name "[I", a three-dimensional array with the element type of byte "[[[[[]] and a two-dimensional array with an element type of Object" [[Ljava/lang/object].

A multidimensional array is represented as an array of arrays. For example, a two-dimensional array of type int is represented as a one-dimensional array in which each element is a reference to a one-dimensional int array, such as:

  

Each array object in the heap must also hold the data when the array's length, array data, and some reference to the class data of the array. The virtual machine must be able to get the length of this array through a reference to an array object, access its elements through an index (during which to check if the array bounds are out of bounds), invoke the method of the direct superclass object declaration of all arrays, and so on.

Program counter

For a running Java program, each of these threads has its own PC (program counter) register, which is created when the thread is started, the size of the PC register is a word length, so it can hold a local pointer and can hold a returnaddress. When a thread executes a Java method, the contents of the PC register are always the "address" of the next instruction to be executed, where the "address" can be a local pointer or an offset in the method bytecode relative to the method's start instruction. If the thread is executing a local method, the value of the PC register at this time is "undefined".

Java stack

Each time a new thread is started, the Java Virtual machine assigns it a Java stack. The Java stack saves the running state of a thread in frames. The virtual machine only performs two operations directly on the Java stack: the stack and the stack in frames.

The method that a thread is executing is called the current method of the thread, the stack frame used by the current method is called the current frame, the class to which the current method belongs is called the current class, and the current class's Chang is called the current constant pool. When a thread executes a method, it keeps track of the current class and the current constant pool. In addition, when the virtual opportunity is inside the stack operation instruction, it performs operations on the data in the current frame.

Each time a thread invokes a Java method, the virtual machine presses a new frame into the Java stack of the thread. This new frame naturally becomes the current frame. When executing this method, it uses this frame to store data such as parameters, local variables, intermediate operation results, and so on.

Java methods can be done in two ways. A return returned by return, known as a normal return, which is terminated abnormally by throwing an exception. Either way, the virtual machine pops the current frame out of the Java stack and frees it so that the frame of the previous method becomes the current frame.

All data on the Java frame is private to this thread. No thread can access the stack data of another thread, so we do not need to consider the access synchronization of stack data in multithreaded situations. When a thread calls a method, the local variables of the method are saved in the frame of the calling thread's Java stack. Only one line Cheng Nen always accesses those local variables, that is, the thread that invokes the method.

Local method Stack

All of the runtime data areas mentioned earlier are clearly defined in the Java Virtual Machine specification, and in addition, it is possible for a running Java program to use some data areas related to local methods. When a thread calls a local method, it enters a completely new world that is no longer restricted by the virtual machine. The local method can access the runtime data area of the virtual machine through the local method interface, but more than that, it can do anything it wants to do.

Native methods are inherently dependent on implementation, and the designers of virtual machine implementations are free to decide what mechanism to use to let Java programs invoke local methods.

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. However, when it calls the local method, the virtual machine keeps the Java stack intact, and no longer presses the new frame into the thread's Java stack, and the VM simply dynamically connects and invokes the specified local method directly.

If a virtual machine implements a local method interface that uses the C connection model, then its local method stack is the C stack. When a C program calls a C function, its stack operation is deterministic. The arguments passed to the function are pressed into the stack in a certain order, and its return value is passed back to the caller in a deterministic manner. Again, this is the behavior of the local method stack in the virtual machine implementation.

It is likely that the local method interface needs to callback the Java method in the Java virtual machine, in which case the thread will save the state of the local method stack and go to another Java stack.

Depicts a scenario where a local method calls back another Java method in a virtual machine when a thread invokes a local method. This image shows a panorama of the threads running inside the Java Virtual machine. A thread may execute a Java method throughout its lifecycle, manipulate its Java stack, or it may jump between the Java stack and the local method stack without hindrance.

The thread first calls two Java methods, and the second Java method calls a local method, which causes the virtual machine to use a local method stack. Suppose this is a C language stack in which there are two C functions, the first C function is called by the second Java method as a local method, and the C function calls the second C function. The second C function then callbacks a Java method (the third Java method) through the local method interface, and finally the Java method calls a Java method (which becomes the current method in the diagram).

Learn Java students pay attention to!!!

You are welcome to join the Java Learning Exchange Group when you encounter any problems in the learning process or want to acquire learning resources: 299541275 We'll learn java! together.

Java Virtual Machine Architecture

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.