InsideJVM

xiaoxiao2021-03-06  76

Class loader system

The class loader is the first defense line of the sandbox. After all, the code is loaded into the JVM, which includes dangerous code. Its security effect is three points:

A protection of good-time code is not affected by malicious code Second Protection The verified class library three-generation code is placed in various protection domains with different behavior restrictions.

The class load system protects the kind of codes from malicious code by using a different type of loader to put the classes in different namespaces.

JVM maintains a namespace for each class loader. For example, if JVM loads a class called Volcano in a certain name space, you cannot load another class also known as Volcano in this name space unless you create another name space. That is, if the JVM has three namespaces, you can load three classes called Volcano, one name space.

In JVM, the class in the same name space is to interact directly, but the class in different namespaces will not be, unless otherwise mechanisms. In this way, the namespace play a role of a barrier.

In Figure 3-1, two namespaces are shown, each having a class loader, each loaded two types, two namespaces have a type called Volcano. The left color deeper class loader loads Type Climber and Volcano, and the shallower-loaded type loader on the right is loaded with Type Bakingsoda and Volcano. The arrows in the figure indicate the names in the namespace to define data in the method area (Method Area). Because of the barrier of the name space, when the Climber references Volcano, it refers to the Volcano in the same name. Although all in the same JVM, it can't know Volcano in another name space. If you want to know how to achieve the separation of the name space, you can see Chapter 8 "Link Mode"

The class loader system protects the security of the credit package by loading the trusted packages and untrusted packages). Although you can develop access controls to the types in the same package, this control works only if it is loaded by the same loader.

Typically, a user-defined class loader needs to rely on other class loaders to complete tasks, at least one class loader created at JVM startup, this class loader is called a start-up class loader. Before the 1.2 version, the class loader must display other class loaders, such as calling the LoadClass method of the other user-defined class loader, or calls the Static Functions of the Bootstrap Class Loader FindsystemClass (). In the 1.2 version, a class loader requires another class loader to load a type of process is standardized as a proxy mode (Parent-Delegation Model:) CHAIN ​​OF RESPONSIBILITY mode)

When a class loader is trying to load a class in its own way, it first defaults to this work to his parent object. This parent object will first hand over this task to his parent object, so this task will pass to the start-up class loader because the start-up class loader is usually the last class of the proxy chain. If the parent class loader loads this type, this type will be returned, otherwise by subclass loader processing. In the implementation of the previous version of the 1.2 version, the built-in loader is responsible for loading the local available class files, typically includes the Java application class file and all the libraries needed for all the applications, although the way the required class file is loaded according to the application Different, many applications searches for the path defined by class path.

In version 1.2, the task loaded with the local available class file is decomposed to a plurality of class loaders. The type loader called the primordage-loader (PRIMORDIAL CLASS Loader) is renamed to the start-up class loader, used to indicate that it is only used to load the core Java API class file, because the core Java API class file is used to start JVM of. The task responsible for loading other class files gives the user-defined class loader (the translator: herein refers to the implementation of the virtual machine), these class files include the application class file, used to install and download. Standard extension class files used to find class files such as libraries in Class Path. Therefore, when 1.2's JVM starts running, it creates at least one user-defined class loader, all of which are stringed into a chain, and the header loader in the chain is the system class. System Class Loader. Prior to 1.2, sometimes it is said that the in-button loader is a system class loader, at 1.2, which is more formally used to refer to the new class loader created by the Java application.

This default parent agent typically loads the initial class of the application, but any user-defined class loader may be changed by the designer of the Java platform. For example, if you write an app, this app needs to install a class loader to load class files downloaded from the network. This app runs on a JVM, and this JVM has two user-defined class loaders, one is to install the extended class loader and the other is the classpath type loader. They are stringed into a chain and the start-up type loader, in turn: Start the class loader, install the extended class loader, class path loader.

As shown in Figure 3-2, the class path loader is designed to be a system class loader, which will be the father of the Java application new type loader. When your application's network-based loader is installed, it sets this system class loader as its father.

If you need to load a class called Volcano in the Java application, your class loader will first hand over this task to its father, class path class loader, to find and load this class file. The classpath loader is also given to our father, install the extended class loader, and complete the task. In this way, this task is finally handed over to the start-up class loader to first try processing.

Assume that the class Volcano is not part of the Java API, nor isn't a part of the installation extension and classpaths. All corresponding class loaders have not returned this type so that they will turn your own class loader. It will download this file from the web so that this class is called part of your application. We continue this example, if a method of Core Volcano is called for the first time later, this method references the class java.util.hashmap in the Java API, and this class is the first reference to this app, so JVM Ask your class loader to load this class. As before, this request finally reached the start-up class loader.

But this time, the start-up class loader can load java.util.hashmap and return it to your class loader. This installing the extended class loader and class path class loader only played a way of delivery, and your class loader does not have to download this class file from the web. Since then, in class Volcano, all references to java.util.hashmap will use this class.

With this background knowledge, we can see how the class loader is used to protect the trusted libraries. The class loader system protects the boundary of the credible class by preventing untrusted classes, preventing potential threats to Java Runtime security. With this chain proxy relationship, we know, to load a class, you need to check the class loader on the chain to check by a specific order, so your defined class loader is always in a lower priority status, if yourself The class loader wants to download a class called Java.lang.integer from the network. It can only use the type from the parent class loader. In this way, the occurrence of trusted code is prevented from replacing the trusted code. But if the code is not prepared to replace a trusted type, just want to insert a new type in the 可 信 包? If in the previous example, your network-based loader wants to load a class called Java.lang.virus. As before, the load-loaded request is passed in the chain until the class loader is started, although the launch class loader is responsible for loading the core Java API class, including a package name called java.lang, but can't find Virus, We assume that this class is also not found in the installation of extended class loaders and classpath type loaders. This way your network loader downloads this class from the web. Suppose you have successfully downloaded class java.lang.virus, and Java has certain privileges for mutual access to classes in the same package. Therefore, because your class loader loads a shameless claim to be part of Java.lang.virus, you must have a certain privilege, thus doing some sinful. However, the class load mechanism stops the occurrence of this matter because the class loading mechanism restricts this privilege only under the premise of loading the same class loader.

Because the credibility class in the Java API's java.lang package is loaded by the startup class loader, the evil java.lang.virus is loaded by your network loader, they don't belong to the same run package (Runtime package) .

Running package This term first introduced in the JVM second edition specification, refers to the same package loaded by the same class loader. The JVM is also confident that the two types are loaded by the same class loader before allowing two types to be accessed in the same package. Therefore, JVM does not allow java.lang.virus to access other types of java.lang packages in the Java API because they are not loaded by the same class loader.

One of the purposes of introducing a run package is to load different types of class files using different class loaders. The start-up class loader is used to load the most trusted core Java API. Installing the extended class loader to load any class files for installation extensions. Although the installation extension is also trustworthy, it has not yet to add a new type of type to the Java API. Similarly, the class loaded by the classpath loader can also access the type of installation extension and the type in the Java API.

The type loader can also simply prohibit loading certain types to protect trusted code.

For example, you may have some packages, some of which you want to load by the class path class loader, not your network loader. Suppose you create a package called AbsolutePower and install it within the access range of the classpath type loader. At the same time, you want to load the class loaded by your class loader to load any classes in the AbsolutePower package. In this way, the first thing in your class loader is that the class that needs to be loaded is not declared as the class in AbsolutePower. If yes, an exception is thrown, not handed over to the parent class loader. In addition to shielding different namespaces, the class loader mechanism is maintained outside the different namespace, and puts each loaded class into a protected domain, and the protection domain has a definition of the activity range of the class.

Class loader subsystem

The class loader subsystem refers to a subsystem responsible for finding and loading types in the JVM system. JVM has two types of loaders: start the class loader and user-defined class loader. The former is part of the JVM implementation, the latter is part of the Java application. The classes loaded by different class loaders are placed in different namespaces of the JVM. The class loader subsystem includes several other parts of JVM, using several classes in the Java.lang library. For example, a user-defined class loader inherits class java.lang.classloader. The ClassLoader method provides an interface to access the JVM class loader subsystem. In addition, both the class loader, the class loader creates an instance of java.lang.class to describe this class. The user-defined instance of the user-defined type loader and Class is also placed in the heap. Loaded type information is placed in the method area.

Load, link, and initialization

In addition to positioning and loading binary files, class loader subsystems must also guarantee the correctness of class files, assigning memory and initialization and resolution of symbolic references for class variables. These behaviors strictly follow the order of the following:

Loading: including positioning and loading a type of binary data link: including verification, preparation, and resolution (optional) a verification: Confidential import type correctness B Prepare: Assignment of the class variable allocation and initialization C parsing: Initialization for direct reference: activation of the initialization of class variables Java code

Launch class loader

JVM must be able to identify and load classes and interfaces in binary files that match the class file format. In addition to class files, JVM implementations can also identify other files.

The start-up class loader is required to implement each JVM, which knows how to load the credibility of the Java API. The JVM specification does not define how the startup class locates class file, which will be grasped by the JVM implementation.

The start-up class loader must be able to generate this type of defined data according to a complete valid type name. A common method is provided on the Windows98 platform using Sun's 1.1 JDK JVM implementation. The start-up class loader searches through all the paths defined in the environment variable ClassPath until this class definition file is found, the name of the class definition file is ".class". Usually a class has a package, the startup class loader will go to the corresponding subdirectory, such as a class called java.Lang.Object, the startup class loader will be in the javalang directory of all defined paths in the ClassPath path Find a class called Object.class until it is found.

In version 1.2, the startup class loader is only found in the system class installation directory instead of all directories defined in the classpath. This task is handed over to the system class loader. The system class loader is a user-defined class loader that is automatically created when the JVM is started.

User-defined class loader

Although the user-defined class loader must have a Java app, but can interact with JVM through its four functions. // Four functions declared in class java.lang.classloader: protected final class defineclass (string name, byte data); protected final class defineclass (string name, byte data, int 网OFFSET, INT Length, ProtectionDomain; Protected Final Class FindSystemClass (String Name); Protected Final Void ResolVeclass (Class C); any JVM implementation must connect these four functions to the internal class loader subsystem. Both defineClass () methods have a type of input parameters named Data [], defineClass () hopes that data in Data [Offset Length] is a legitimate type of data, this new The type will be placed in the specified protected area, if the first defineClass method is placed in the default protected area, each JVM implementation must ensure that DEFINECLASS can put the new type in the method area.

The FindSystemClass () method is parameter in a type name. At 1.0 and 1.1 versions, this method will load this type by starting the class loader. If the class loader has loaded this type, it returns a Class object that describes this type. If you don't find it, you will throw a classNotFoundException. In version 1.2, the FindSystemClass () method loads this type through the system class loader. Regardless of the type of loader, its external behavior is specified.

The resolveclass () method receives a reference to the Class object. It links the type represented by this Class object.

Name space

Each class loader has its own namespace, so a Java application can load multiple times for the same type. Such a type of complete valid name is not enough to determine the uniqueness in the JVM. When there are multiple type loaders loaded the same type, in order to uniquely determine the type, you must add the name of the class loader before the type name.

In addition to the data of the load type, the JVM also records the type of loader. When JVM parses a symbolic reference to another class, JVM guarantees the same class loader with reference classes to the class loader.

The method area is stored inside the JVM instance, and the type information is stored in a memory logical area called method area. Type information is extracted from the class file when the class loader is loaded. Class (static) variables are also stored in the method area.

The designer implemented by JVM determines the internal performance of type information. For example, multi-byte variables are stored in Big-endian, but after loading into the method area, its storage is specifically defined by the JVM according to different platforms.

JVM should use a lot of type information stored in the method area when running applications. In addition to the type of information, the designer has to consider space issues in addition to improve the operating efficiency of the application as much as possible. According to different needs, the implementation of JVM can pursue a balance in time and space.

Because the method area is shared by all threads, the thread safety of the data must be considered. If the two threads are trying to find the Lava class, if the LAVA class has not been loaded, there should be only one thread to load, and the other thread is waiting. The size of the method area is not necessarily fixed, and the JVM can be dynamically adjusted according to the needs of the application. The same method area is not necessarily continuous. The method area can be allocated in a heap (even virtual machine yourself). JVM can allow users and programs to specify initial size, minimum, and maximum size of method area.

The method area also exists garbage collection, as the Java program can be dynamically expanded through the user-defined class loader, and some classes will become garbage. The JVM can reclaim the space that is not cited, so that the space is minimized.

Type information For each load type, JVM must store the following types of information in the method area: One of the full and valid names of this type Direct parent class (unless this type is Interface or java.lang.Object In both cases, there is no parent class) Three this type of modifier (a subset of the public, Abstract, Final) Four of this type of direct interface.

Type names appear in full and valid names in Java class files and JVM. In the Java source code, the full and valid name is added by the package name of the class. ", Plus the class name. For example, the package of class Object is java.lang, then its full name is java.lang.object, but in the class file, all "." Is replaced by slash "/", it will become Java / Lang / Object. The full and effective names in the method area are different depending on different implementations.

In addition to the above basic information, JVM also saves the following information for each type: a constant pool information (Method) information, in addition to all static variables outside of the constant

The constant pool JVM maintains a constant pool for each loaded type. The constant pool is a ordered collection of constants for this type, including actual constants (String, Integer, and Floating Point constants) and symbolic reference to types, domain, and methods. The data item image number group item in the pool is accessed by indexing. Because the constant pool stores all types, domains and methods used in the type, the domain and methods of the domain, and methods, it plays a core role in the dynamic link of the Java program.

Domain information JVM must save the relevant information of all domains of the type in the method area and the order of the domain declaration, the domain information includes: domain name domain domain modifier (Public, Private, Protected, Static, Final Volatile, TraSient Set) Method Information JVM must save the following information of all methods, the same domain information, the same domain information, the quantity of the return type (or VOID) method of the declaration order method method, the modifier of the type (ordered) method (public, private, A subset of Protected, Static, Final, Synchronized, Native, Abstract In addition to the Abstract and Native methods, other methods also have the size of the bytecode of the save method (Bytecodes) Operation Stage and the size of the local variable zone of the stack frame. table

Class Variables (Class Variables Translator: It is a static variable of the class, which is only related to the class, so it is called a class variable) class variable shared by all instances of the class, even if there is no class instance you can access it. These variables are only related to the class, so in the method area, they become a logical part of the class data. Before the JVM uses a class, it must allocate space for each Non-Final class variable in the method area.

The processing method of constant (class variables declared for Final) is different, and each constant has a copy in the constant pool. The Non-Final class variable is stored in a declared class information, while the Final class is stored in all types of information using it. The reference JVM for the class loader must know that a type is loaded by the boot loader or is loaded by the user class loader. If a type is loaded by the user class loader, the JVM saves one reference to the class loader as part of the type information in the method area.

JVM needs this information when dynamic links. When parsing a reference to another type, JVM needs to ensure that both types of class loaders are the same. This is critical to the way JVM distinguished name space.

The reference JVM for the Class class is an instance of java.lang.class for each load (translator: including classes, and interface). The JVM must link the instance of the Class and the type data stored in the method area in some way.

You can get this instance of this instance with a static method of the Class class // a method declared in class java.lang.class: public static class forname (String classname);

If you call Forname ("Java.Lang.Object"), you will get the class objects corresponding to java.lang.object. You can even get any loaded class references in any package through this function, as long as this class can be loaded into the current namespace. If the JVM cannot load the class to the current name space, the Forname will throw the classNotFoundException. (Translator: Friends who are familiar with COM will definitely think that there is a stuff called class objects in COM, which is mainly a factory model, while Java has JVM's intermediate layer. Class objects can easily provide more information. These two types of objects are Singleton)

You can also get a reference to the class object by a getClass () function of any object, getClass is declared in the Object class: // a method declared in class java.lang.object: public final class getclass (); for example, if you have A Java.lang.integer's object reference can activate getClass () to get the corresponding class reference.

Through the reference to the class object, you can get the type information stored in the method area in the run. Here is some of the Class class: // some of the methods declared in class java.lantic.class: Public String getname (); public class getsuperclass (); public boolean isinterface (); public class [] getInterfaces (); public classloader getClassLoader ();

These methods can only return information that has been loaded. GetName () Returns the full name of the class, getSuperClass () returns the class object of the parent class, isinterface () determines if it is an interface. GetInterFaces () Returns a set of class objects, each class object corresponds to a direct parent interface. If not, return a length of zero. GetClassLoader () Returns a reference to the class loader if it is loaded by the start-up class loader. All of this information is obtained directly from the method area.

Method Table In order to improve access efficiency, it must be carefully designed to store the data information structure in the method area. In addition to the structures discussed above, the implementation of JVM can also add some other data structures, such as method tables. JVM adds a method table to each loaded non-virtual class, the method table is a set of direct references to class instance methods (including methods from parent class inheritance). JVM can quickly activate the instance method by method table. (Translator: The method table here is the same as the virtual function table in C , but the Java method is Virtual, nature does not need to be virtual. It is like Java claims that there is no pointer, in fact, Java is all pointers. Safer Just add a more complete inspection mechanism, but this is at the expense of efficiency, the individual believes that Java designers have always put safely above efficiency, and all Java is more suitable for network development) an example in order to display JVM How to use the information in the method area, we use an example, let's look at the class: Class Lava {Private Int speed = 5; // 5 KilometerS per hour void flow () {}}

Class Volcano {Public Static Void Main (String [] args) {lava lava = new lava (); lava.flow ();}} How to describe the paragraph code of the first instruction of the main () method implemented. Different JVM achievements are very different, just one of them.

In order to run this program, you pass "Volcano" to JVM in some way. With this name, JVM found this class file (Volcano.class) and read it, it extracts the type information from the class file and placed in the method area, by parsing the bytecode in the method area, JVM is activated MAIN () method, when executed, JVM maintains a pointer to the Volcano constant pool.

Note that the JVM has already begun to execute when the LAVA class has not been loaded. Just like most JVMs, not all classes have only been loaded in the future, it will only load when needed.

The first instruction of Main () informs the JVM to assign enough memory for classes listed in the constant pool. JVM uses a pointer to the Volcano constant pool to find the first item, discovery is a symbolic reference to the Lava class, then it checks if the method area is to look at whether Lava has been loaded.

This symbol reference is just a full and valid name "Lava" of the class LAVA. Here we see that the JVM can find a class from a name as soon as possible, how important is a good data structure. Here, the implementation of JVM can adopt various methods, such as Hash tables, lookup trees, and the like. The same algorithm can be used for the implementation of the Forname () of the Class class.

When the JVM discovery has not been loaded with a class called "Lava", it starts to find and load the class file "lava.class". It extracts type information from class files and placed in the method area.

The JVM then replaces the symbolic reference of the constant pool first item with a pointer directly pointing to the method area Lava class. You can quickly find the LAVA class with this pointer. This replacement process is called constant pool resolution. Here we replace a Native pointer.

JVM finally assigned space for the new Lava object. This time, JVM still needs information in the method area. It uses a pointer to LAVA data (just pointing to the first item of the Volcano constant pool) to find how many spaces do it require.

JVM always knows the space required for a type of object from the type information stored in the method area. But an object may require different spaces in different JVMs, and its spatial distribution is also different. (Translator: This is a truth with different object models in C , different compilers is a truth)

Once JVM knows the space you want a LAVA object, it assigns this space on the heap and initializes the variable SPEED of this instance to the default value. If the Lava's parent object also has an instance variable, it will also be initialized. When the reference to the newly generated LAVA object is pressed into the stack, the first instruction is over. The following instructions use this reference to activate the Java code to set the speted variable to the initial value, 5. Another instruction uses this reference to activate the flow () method of the LAVA object.

Piles a Java application All class instances or arrays created in the run are placed in the same heap and share all threads. Because a Java application is only a JVM instance, each application has a heap of each application, it is impossible to destroy the heap of another application. However, a multi-threaded application must consider synchronous problems.

JVM has instructions to allocate objects in the heap, but does not release the object's instructions. As you can't release an object with Java code, the bytecode has no corresponding function. The application itself does not have to consider when and what method is used to recycle the memory that does not use the object. Typically, JVM handed this task to the garbage collector.

The main job of garbage collection a garbage collector is to recover the memory occupied by the object that is not referenced. It may also go to move the object still used to reduce memory fragmentation.

The JVM specification does not specify what technology is used for garbage collection, which is determined by the implementation of JVM. Because there may be many places, such as Java stack, heap, method area, Native Method stack. Therefore, the use of garbage collection techniques largely affects the design of the running data area.

Like the method area, the heap does not have to be a continuous memory area, or the size can be dynamically resized according to the needs. The method area can be placed on the top of the heap. In other words, the type information and the actual object are all on the same pile. The garbage collector responsible for cleaning the object may also be responsible for recycling. The initialization size of the heap, the maximum minimum size can be specified by the user or program.

Object Reperestation (Translator: C , called Object Model) The JVM specification does not specify how objects are in the heap. The performance of the object affects the entire design of the heap and garbage collection, which is determined by the JVM implementation.

The main data of the object is composed of instance variables declared by the corresponding class and its parent class (INSTANCE VARIABLES translator: Class Variables, Class Variables is stored in the method area, this is in the upper translation) JVM should be both from one Object reference quickly finds instance variables, and it is also possible to quickly find class data stored in the method area. Therefore, there is often a pointer to the method area in the object.

One possible implementation is to divide the heap into two parts: a handle pool and a target pool. Figure 5-5 An object reference is a native pointer to the handle pool. Each entry of the handle pool has two parts: a pointer to the object instance variable, a pointer to the method area type data. The advantage of this design is to make the stack of sorting, when moving the object to reduce fragmentation, do not need to update each object reference, and only change the handle. The disadvantage is that each access object is passed twice.

Figure 5-5

Another design is to direct the object pointer directly to the object instance variable, and in the object instance contains a pointer to the method area type data. The advantages and disadvantages of such a design are just the opposite of the previous method. Figure 5-6.

Figure 5-6

JVM has several reasons to enable it to get the corresponding class data from the object reference. 1. When the application tries to transform (CAST), JVM needs to ensure that the type of rotation is that this type itself or the parent type of this type. 2. 3 when the application performs instanceOf operation. When an instance method is activated, the JVM must perform dynamic binding, and what it depends on is not the type of this reference, but the information corresponding to this object.

No matter what the object is manifested, it seems to have a methodometer that can be easily accessible. Since the method can accelerate the call of the instance method, the performance of the JVM has an important impact. The JVM specification does not specify whether you must use a party, such as in an environment where the memory is rare, may not afford the memory spending of the method table. However, if the method table is used, it should be able to get quickly from an object reference. Figure 5-7

Figure 5-7 shows an implementation of a link method table and an object reference. The data of each object contains a pointer to a special data structure. This data structure is located in the method area, which includes two parts: one of the methodological table method table method table method table for the method area corresponding to class data. It is a pointer to method data, and method data comprises: one of the operand stacks of this method and the size of the two-way method of the local variable zone, three exception tables are sufficient JVM to activate a method. The function pointer of the method table includes a function of the class or its parent class declaration. That is, the function points to the method table may be such a statement, or it may be inherited.

If you are familiar with C internal working principle, you will find that this is very similar to C VTBL. In C , the object consists of an instance data and a pointer pointing to the virtual function, and the JVM can also use this method. JVM can add a method table for each object in heap, which takes more memory than Figure 5-7, but can improve some efficiency. This solution is applicable to a systemic system. (Translator: I always feel that the author is misunderstood for C , and the design of C in the function table is similar. In the case of a virtual function (not considering more inheritance), each object is only A pointer to the vTable, while vtable is also associated with classes.)

In addition to the example data shown in Figures 5-5 and 5-6, the object data has a logical part, which is an object lock (Object's Lock). Each object in the JVM has a lock for synchronization when multi-threaded access. Only one thread has this object lock at a moment, and only this thread can access the data of the object. Other threads to access this object are only waiting until the thread ownership is released. When a thread has an object lock, you can continue to add a request. But a few times must be released several times.

Many objects may not lock in their lifetime, which does not require additional data, as shown in Figures 5-5 5-6, there is no pointer to lock data in the object data. Only when you need to lock, you need to lock data, but other methods need to contact object data and corresponding lock data, such as in a tree that locks the lock data in an object address.

In addition to data that implements locks, each Java object is logically added to data to be synchronized. The lock is used to implement mutual exclusive access to shared data, while synchronization is to achieve multiple threads to work together to complete a common goal.

Synchronization is achieved by a waiting method and notification method. Each class has inherited three waiting methods from Object (three called WAIT () overload functions) and two notification methods (notify () and notifyall ()). When a thread calls the WAIT method on an object, JVM blocks this thread and put it in the WAIT Set of this object. When a thread calls the notification method in this object, JVM will wake up one or more threads waiting for a centralized block at a certain time. Like lock data, not every object requires synchronization data. Many JVM implementations separate synchronization data from object data, only to create synchronization data for this object when needed, is typically called waiting methods or notification methods in the first call.

Finally, an object may also contain data related to garbage collection. Garbage collection must track each object, this task inevitably attaches some data, the type of data is determined by the algorithm of garbage collection. For example, if the garbage collection uses the flag clearance algorithm, you must have a data to mark whether this object is referenced. Like the thread lock, these data can be placed outside the object. Some garbage collection techniques only require additional data at runtime. For example, the flag clearance algorithm uses a bitmap to mark the reference of the object. In addition to the reference of the logo object, the garbage collection also distinguishes whether an object calls Finalizer. Before collecting an object, the garbage collector must call the object that declares the class of Finalizer. Java language specification points out that the garbage collector can only call Finalizer for an object, allowing this object to resurrect, even if it is again referenced again. This will no longer call Finalizer when this object is collected again. There are not many objects of Finalizer, and there are fewer objects, so it is rare to reclaim two times for an object. This is logically logically a part of the object, but is usually saved separately from the object.

Array Performance in Java, an array is a mature object. Like other objects, the array is also stored on the heap, and the designer implemented by the JVM also has the right to determine the performance of the array.

An array also has a related class instance (Class Instance), all of which have an array of the same dimensions and types as a class, regardless of the length of the array (the length of each dimension of the multi-dimensional array). For example, an array with three INTS and an array with six INTS is the same class. The length of the array is only related to the instance data.

The name of the array class consists of two parts, one is the type represented by the dimension and one character represented by '['. For example, the class name "[i" of the one-dimensional array of type INTS is. The three-dimensional array of type Bytes is "[[[[[[[[[[b". The type of two-dimensional array of objects is "[[ljava.lang.Object".

The multidimensional array is expressed as an array of arrays. For example, a two-dimensional array of type INTS will be represented as a one-dimensional array, and the array element is a reference to a one-dimensional INTS array. Figure 5-8

Figure 5-8

The data that must be saved for each array is the length of the array. The JVM must be able to get the length of the array from an array, access the array element, check whether the array subscript is off, and activates the Object declaration.

Java stack JVM allocates a stack for each newly created thread. The stack saves the state of the thread in a frame-based unit. JVM only performs two operations on the stack: stack and out of the stack in frames.

The method that a thread is performing is called the current method of this thread. The current method is called the current frame. The class belongs to the current method is called the current class. The constant pool of the current class is called the current constant pool. When the thread performs a method, it tracks the current class and constant pool. When the JVM performs the operation of intra data within the current frame.

When the thread activates a Java method, the JVM will press a frame in the Java stack of the thread. This frame naturally became the current frame. This frame will be used to save parameters, local variables, intermediate calculation processes, and other data during this method.

One method can end in two ways. One is the end of the normal return. One is an abnormality ending (Abrupt Completion). Regardless of the way, JVM will pop up the current frame and release it, so that the frame of the previous method becomes the current frame. (Translator: It may be possible to understand, the frame located at the top of the stack is the current frame)

All data on the Java stack is privately available. A thread cannot access the stack data of another thread, so if you do not need to synchronize the stack data in the case of multi-thread.

Like method area and heap (see previous translation), Java stacks and frames do not have to be continuous in memory. The frame can be distributed in a continuous memory area or not. The data structure of the frame is determined by the implementation of the JVM, which allows the user to specify the initial size or maximum minimum size of the Java stack. The Stack Frame Stack Frame has three parts: local variable area, operand stack, and frame data area. The local variable zone and the size of the operand stack should be determined by the corresponding method. The compiler calculates each method when compiling and placed in the class file. The size of the frame data area is certain for a JVM implementation. When the JVM activates a method, it obtains the size of the local variable area of ​​this method from class information data and the size of the operand stack, and the size of the appropriate stack frame is pressed into the Java stack accordingly.

The local variable area of ​​the local variable zone Java stack frame is an array of zero types for a word. The instructions use this data by index. The value of INT, FLOAT, REFERENCE and RETURNADDRESS occupies an array, and the value of type Byte, Short, and Char is turned to an int value before depositing in an array. The value of the type long and double occupies two consecutive items, when accessing them, the instruction provides the index of the first item. For example, a long value occupies 3, 4, and the instruction will take the LONG value of the index 3. All the values ​​of the local variable zone are all words, and the starting index values ​​of Long and Douplas are not limited.

The local variable zone contains the parameters and local variables of this method. The compiler first places the parameters in the local data area in the order of declaration. Figure 5-9 shows the variable zone of the following two methods. // ON CD-ROM IN File JVM / EX3 / EXAMPLE3A.JAVACLASS EXAMPLE3A {

Public Static Int RunclassMethod (INT I, Long L, Float F, Double D, Object O, BYTE B) {

Return 0;}

Public Int RuninstancethMethod (Char C, Double D, Short S, Boolean B) {

Return 0;}}}

Figure 5-9. Method parameters in the local variable area

Note that in the frame of the method runinstanceMethod (), the first parameter is a value of a type Reference, although the method does not display the parameters, but this is a parameter that is implicitly added to each instance method (Instance method) Value, used to represent the call to the call. (Translator: Like the THIS pointer in C ) We look at RunclassMethod () does not have this variable, because this is a class method, class method and class, not related to the object.

We noticed Byte, Short, Char, and Boolean in the source code into INTS in the local variable area. The same situation is also the same. As mentioned earlier, JVM does not directly support the Boolean type, and the Java compiler always uses INTS to represent Boolean. However, Java is supported by Byte, Short and Char, which can be stored as an instance variable in a local variable area, or may be stored as class variables in the method area. However, in the local variable zone and the operand stack, it is converted to the value of the INTS type, and the operation is also int click, only when the reactor or method area will turn back to the original type.

It is also necessary to pay attention to the object O of RunclassMethod (). In Java, the object is passed in Reference. All objects are stored in the heap, you will never find the copy of the object in a local variable area or operand stack, and there will be an object reference.

The compiler can be used in a variety of placement methods of local variables, which can arbitrarily determine the order sequence, and can even use an index to refer to two local variables. For example, when the scope of the two local variables do not overlap, such as the local variables I and J of Example 3b. // ON CD-ROM IN File JVM / EX3 / EXAMPLE3B.JAVACLASS EXAMPLE3B {

Public static void runtwoloops () {

For (int i = 0; i <10; i) {system.out.println (i);

For (int j = 9; j> = 0; --j) {system.out.println (j);}}}

The implementation of JVM is still the same flexibility like other data regions. How to distribute the long and double data in an array, the JVM specification is not specified. If a JVM implemented word length is 64 bits, you can put the long or double data in the number in the array, and the high item is empty. (When the word length is 32, it is necessary to put down a long or double).

The operand stack operand is the same as a local variable region that stores data with an array of Word, but it is not accessed by an index, but is pressed and popped in a stack. If an instruction is pressed into a value, another instruction can pop up this value and use it.

JVM is the same as the processing data type in the operand stack, and the local variable zone is the same as the conversion of data types. The JVM does not have a register, and the JVM is based on the stack rather than registers, because JVM's instructions get operands from the stack, not registers. Although operands can be obtained from other places, such as by nodes, or within a constant pool, but mainly from the stack.

JVM uses the operand stack as a work area. Many instructions pop up data from this stack, perform operations, and then press the result. For example, the IADD instruction pops up from the stack, adds, then press the result. The following shows how JVM performs this action: iLoad_0 // push the int in local variable 0iload_1 // push the int in local variable 1iadd // Pop Two INTS, Add THEM, PUSH RESULTISTORE_2 / / POP INT, Store Into Local Variable 2

In the sequence of this byte code, the first two instructions iLoad_0 and iLoad_1 will be stored in the integer of the index of 0 and 1 in the local variable zone, and then add the result into the operational data area. Article 4 Instructions ISTORE_2 pops up from the operation data area and stores the local data area index of 2. In Figures 5-10, the process is described in detail, in the figure, the area where the use is expressed in a blank.

Figure 5-10. Two partial variables are added.

In addition to the local variable zone and the operation data stack, Java stack frame also requires data to support constant pool resolution, normal returns and exception distributions (Exception Dispatch). This information is saved in the frame data area.

Many instructions in the JVM involve data on a constant pool. Some instructions are merely removed in the constant pool and press into the operand stack. Some instructions use data in the constant pool to indicate the class or array that needs to be instantiated, the domain that needs to be accessed, or the method that needs to be activated. There are also some instructions to determine if an object is a descendant example of a certain class or interface specified by a constant pool.

Whenever JVM is required to perform an instruction that requires constant zone data, it will access the constant region through a pointer to the constant zone in the frame data area. Previously, the references for types, domains, and methods were symbols at the beginning of the constant zone. If it is still a symbol when the instruction is executed, the JVM will parse. In addition to the constant zone parsing, the frame data area also helps the JVM processing method to end the normal and exception. Normal end, JVM must restore the environment of the method caller, including recovering the PC pointer. If the method has a return value, the JVM must press the value to press the value of the operand's operator stack.

In order to handle the abnormality of the method, the frame data area must save a reference to this method's exception table. An exception table defines this method being protected by the Catch clause, each of which has the start and start position of the CatCH clause, and the index used to represent an exception class in a constant pool, and the Catch clause The starting position of the code.

When a method throws an exception, JVM uses the exception table specified by the frame array area to determine how to handle it. If you find a matched Catch clause, you will turn over the control. If not found, the method will end immediately. JVM uses the information of the frame data area to restore the caller's frame and then reappears the same exception.

In addition to the above information, the implementation of the JVM can also place additional information into the frame data area, such as debug data.

A implementation of a Java stack can design a Java stack in your own idea. As previously, a method is a separate distribution frame from the heap. I take this as an example, look at the following: // ON CD-ROM IN File JVM / EX3 / EXAMPLE3C.JAVACLASS EXAMPLE3C {

Public static void addandprint () {double result = addtwotypes (1, 88.88); system.out.println (result);}

Public Static Double AddTTwotypes (INT I, DOUBLE D) {Return i D;}}

Figure 5-11 shows three snapshots for performing this method. In this JVM implementation, each frame is individually assigned from the heap. In order to activate the method addTwotypes (), method addandprint () first press the INT 1 and Double88.88 to the operand stack, and then activate the addtwotypes () method.

Figure 5-11. Frame distribution

The command of activation addtwotypes () uses the data of the constant pool, and the JVM finds that this data in the constant pool is resolved if necessary.

Note that addandprint () method uses constant pool reference method addtwotypes (), although these two methods belong to a class. Like other classes, reference to the same class and the domain reference are also symbols in the initial time, which needs to be parsed before use.

The parsed constant pool data item will point to information stored in the method area for information on how to addTWotypes (). JVM will use this information to determine the size of the ADDTWOTYPES () local variable area and the operand stack. If you use Sun's Javac compiler (JDK1.1), the local variable area of ​​the method addTwotypes requires three words, and the operand stack requires four words. (The size of the frame data area is set to a JVM implementation) JVM assigns a stack frame that is sufficiently sized for this method. The Double parameters and int parameters (88.88 and 1) are then popped up from the operating status stack of the method AddandPrint (88.888 and 1) and put them in the local variable area index of the method addtwotype () to 1 and 0.

When addtwotypes () returns, it first presses the return value of the type Double (here 89.88) into its operand stack. JVM uses the information in the frame data area to find the caller (for addandprint ()), then press the return value into the opener stack in the AddandPrint () and releases the stack frame of the method AddTwotype (). The JVM then makes the stack frame of the addtWotype () as the current frame and proceeds to execute method addandprint (). Figure 5-12 shows the same method in different JVM implementations. The stack frame here is in a continuous space. This method allows the stack frame of the adjacent method to overlap. Here, the caller's operand stack is a local variable zone of the tuner.

Figure 5-12. Assigning frames from a continuous stack

This method not only saves space, but also saves time because JVM does not have to copy the parameters from a stack frame to another stack frame.

Note The operating number stack of the current frame is always at the top of the Java stack. Although this may be better illustrated in Figure 5-12. However, regardless of how the Java stack is implemented, the operation of the operand stack is always performed at the current frame. In this way, the operand stack in the current frame is pressed into a value in the Java stack.

There are still other implementations of the Java stack, essentially of the above two types. A JVM can divide a space from the stack at the beginning of the thread. In this continuous space, JVM can use 5-12 overlap. However, in combination with other segment space, the method of Figure 5-11 is used.

转载请注明原文地址:https://www.9cbs.com/read-94332.html

New Post(0)