An overview of the

The Java VIRTUAL machine loads the data describing classes from the Class file to the memory, verifies, converts, parses, and initializes the data, and finally forms a Java type that can be directly used by the VIRTUAL machine. This is the Class loading mechanism of the virtual machine. The above paragraph is a description of class loading in Understanding the Java Virtual Machine. In fact, it is simply a program from the beginning of the.java file to. Class files, which contain Java virtual machine instruction sets and symbol tables, and other auxiliary information that can be used only after being loaded into the virtual machine. Let's discuss how these Class files are loaded and what happens when they are loaded.Copy the code

Class lifecycle

loading

  • When loading

    1. Preloading: The. Class file under rt.class under JAVA_HOME/lib/ is loaded when the VM starts. The class file is often used when Java programs are running, such as java.lang.⁎ and java.util. Runtime loading: When a vm uses a.class file, it first checks memory to see if the.class file has been loaded. If it has not been loaded, it is loaded based on the fully qualified name of the class.Copy the code
  • What does the virtual machine do during load

    1. Get the binary byte stream that defines a class from its fully qualified name. 2. Convert the static storage structure represented by the byte stream into the running data structure of the method area. 3. Generate a java.lang.Class object that uniquely represents this Class in memory, and use it as an entry point for all data about this Class in the method area. (Normally this class object is stored in the heap, but in the HotSpot virtual machine's case, this class object is stored in the method area.)Copy the code
The above three requirements of the virtual machine are not specific. For example, the first one does not specify where and how the binary stream comes from, including the following: From the ZIP package, this is the foundation of the jar, EAR, WAR format from the network, the typical application is the runtime of the Applet computing generation, the typical application is the dynamic proxy technology generated by other files, the typical application is JSP, that is, generated by the JSP corresponding. Class file read from the database, It's rare...Copy the code

validation

As the name implies, it verifies the byte stream of a Class file. The purpose of the verification is to ensure that the current Class file meets the requirements of the Java virtual machine and does not compromise the virtual machine's own security. Generally, the verification includes the following: 1. File format verification is to verify whether the byte stream complies with the Class file specification, which can ensure that the input byte stream can be correctly parsed and stored in the method area. 2. Metadata verification Performs semantic verification on the metadata information of the class. 3. Bytecode verification Is the most complex verification stage. It verifies whether the semantics of the program conform to the specification and logic, and verifies the method body of the class. 4. Symbol reference verification occurs when the symbol reference is converted into a direct reference, which can be regarded as the matching verification of information other than the class itself (the application of various symbols in the constant pool). For example, whether the corresponding class can be found by the fully qualified name described by the string in the symbol reference; Is the class, field, method (private, protected, public, default) accessible to the current class?Copy the code

To prepare

Formally allocates memory and assigns initial values to class variables. 1. Memory is allocated only for class variables, that is, static variables. Instance variables are allocated in the heap along with the object when the instance is initialized. 2. This phase assigns initial values to static variables that are not final. For example, "public static int value = 123;" , value is 0 after the preparation phase instead of 123, and assigning value to 123 will take place during the initialization phase; Public static final int value = 123; On the other hand, in the preparation phase, the vm will assign value to 123. The zero values of the basic data are shown in the following table:Copy the code

parsing

Resolution is the process by which a VIRTUAL machine converts a symbolic reference in the constant pool to a direct reference. 1. Symbolic references This is a compilation principle concept. Symbolic references include the following three types of constants: fully qualified names of classes and interfaces, field names and descriptors, method names and descriptorsCopy the code

All in all, a symbolic reference is the same as what we talked about above, a description of a class, a variable, or a method. Symbolic references are independent of the memory layout of the virtual machine, and the target of the reference is not necessarily loaded into memory.

A direct reference can be a pointer directly to the target, a relative offset, or a handle that indirectly locates the target. Direct references are related to the memory layout implemented by the virtual machine, and the same symbolic reference will generally not translate the same direct reference across different virtual machine examples. If there is a direct reference, the target of the reference must already exist in memory.Copy the code

Initialize the

To begin the actual execution of the Java code defined in the class, the initialization process is the execution of the class constructor <clinit>(). Remember that the previous preparation phase was to assign an initial value to the memory allocated to the class variable. In this case, the class variable is assigned to a value specified by the user. The VM specification defines the initialization scenarios in "Have and Only" 5:1. If the bytecode instruction new, getStatic, putStatic, or Invokestatic is not initialized, the initialization must be triggered first. 2. When a class is called using a method in the java.lang. Reflect package; 3. During class initialization, if the parent class is not initialized, the initialization of the parent class is triggered. When the VM starts, the vm initializes the user class that contains the main() method. 5. When using JDK 1.7 dynamic language support, if a Java lang. Invoke. The final analytical results REF_getStatic MethodHandle instance, REF_putStatic, REF_invokeStatic method handles, If the class to which the method handle corresponds has not been initialized, it needs to be initialized first.Copy the code

Parent delegation model

Before we get to the parent delegate model, let's talk about classloaders. For any class, it needs to be unique in the JVM, both by the class loader that loads it and by the class itself. Each class loader has a separate class namespace. The classloader simply loads a class file into the JVM memory by specifying a fully qualified name, turning it into a class object. From the JVM perspective, there are only two kinds of loadersCopy the code
  • The Bootstrap ClassLoader is a part of the VM that loads classes identified by the VM in the JAVA_HOME/lib/ directory or the path specified by the -xbootclasspath parameter.

  • Other class loaders: implemented by the Java language and inherited from the abstract ClassLoader:

    1. Extension ClassLoader: Is responsible for loading all classes in the

      \lib\ext directory or the path specified by the java.ext.dirs system variable.
    2. Application ClassLoader. Responsible for loading the specified class library on the user classpath, we can use this class loader directly. In general, if we don’t have a custom class loader, we use this loader by default.

The parent delegation model works as follows: If a classloader receives a classloader request, it will not first load the class itself. Instead, it will delegate the request to the parent classloader at each level, so that all the loading requests are passed to the top-level startup classloader. The child loader will only attempt to load the class if the parent fails to complete the load request (it does not find the required class in its search scope). Here is a well-known example of why you should use the parent delegate model.

The hacker customizes a Java.lang. String class that has the same functionality as the system’s String class, with a few modifications to one function. For example, in the equals function, which is often used, the hacker adds some “virus code”. And is added to the JVM through custom class loaders. At this point, without the parent delegate model, the JVM could mistake the hacker’s custom Java.lang. String class for the system’s String class, causing “virus code” to be executed.

With the parent delegate model, the hacker’s custom Java.lang. String class is never loaded into memory. Because the topmost classloader first loads the system’s Java.lang. String class, the final custom classloader cannot load the Java.lang. String class.

Maybe you’re thinking, why don’t I force my own java.lang.String class into my own class loader instead of calling the parent loader? Yes, it works. However, in the JVM, when determining whether an object is of a type, false is returned if the actual type of the object is different from the classloader of the type to be compared.

Here’s a simple example:

ClassLoader1 and ClassLoader2 both load the java.lang.String class, which corresponds to the Class1 and Class2 objects. The Class1 object is not of the java.lang.String type loaded by the ClassLoad2 object.

How to implement the parent delegation model

The principle of the parent delegation model is simple, and the implementation is simple. Each time by delegating to the parent class loader, when the parent class loader fails to load, then loading. The default loadClass method of the ClassLoader class is already written for us, so we don't need to write it.Copy the code

Break the parent delegation model

The parent delegation model is not a mandatory constraint, but rather an implementation of classloaders recommended by Java designers to developers that can "break" the model in order to accomplish certain operations under certain conditions. 1. Re-loadclass method 2. Use Thread Context ClassLoader. This classloader can be set via the setContextClassLoaser () method of the java.lang.thread class. If not already set at the time of Thread creation, it will inherit one from the parent Thread, if not already set globally within the application. That class loader is the application class loader by default. 3. In order to achieve hot swap, hot deployment, modularization, meaning that adding a function or subtracting a function does not need to restart, just need to replace the module with the same class loader to achieve hot replacement of the code.Copy the code

For this article, see Understanding the Java Virtual Machine.

[this mechanism of in-depth analysis of Java (source level)] (http://www.hollischuang.com/archives/199)

[Java class loading, links, and initialization] (http://www.hollischuang.com/archives/201)