1. What is class loading

Loading a class involves reading binary data from a class’s.class file into memory, placing it in the method area of the runtime data area, and then creating a java.lang. class object in the heap that encapsulates the class’s data structure in the method area. The end product of Class loading is the Class object in the heap, which encapsulates the Class’s data structure in the method area and provides the Java programmer with an interface to access the data structure in the method area.

Instead of waiting for a class to be “first actively used” before loading it, the JVM specification allows the classloader to preload a class in anticipation of it being used, and if it encounters a missing.class file or an error during preloading, The class loader must not report a LinkageError until the program first actively uses the class. If the class is never actively used by the program, the class loader will not report an error

How to load. Class files - directly from the local system - Download. Class files from the network - Load. Class files from zip, JAR archives - Extract. Class files from a proprietary database - Dynamically compile Java source files into. Class filesCopy the code

2. Class lifecycle

The process of class loading includes five stages: loading, verification, preparation, parsing and initialization. Of the five phases, the loading, validation, preparation, and initialization phases occur in a certain order, while the parsing phase does not, and in some cases can begin after the initialization phase, in order to support runtime binding (also known as dynamic binding or late binding) in the Java language. Also note that the phases here start in sequence, not proceed or complete sequentially, as these phases are often intermixed with each other, often invoking or activating one phase while the other is executing.

• Load: Finds and loads binary data for a class

Load-time Is the first phase of the class loading process, during which the virtual machine needs to do three things:

Get the binary byte stream defined by a class by its fully qualified name.

2. Convert the static storage structure represented by this byte stream into the runtime data structure of the method area.

3. Generate a java.lang.Class object representing this Class in the Java heap as an access point to the data in the method area.

Compared to other phases of class loading, the loading phase (specifically, the action of the loading phase to retrieve the binary byte stream of the class) is the most controllable, because developers can either use the system-provided class loader to complete the loading, or they can customize their own.

After the loading phase is complete, the binary byte streams outside the virtual machine are stored in the method area in the format required by the virtual machine, and an object of java.lang.Class is created in the Java heap through which the data in the method area can be accessed.

• connection

– Verification: Ensures that the loaded classes are correct

Validation is the first step in the connection phase, which ensures that the byte stream in the Class file meets the requirements of the current virtual machine and does not compromise the security of the virtual machine itself. In the verification stage, four stages of inspection actions will be roughly completed:

File format verification: verify whether the byte stream conforms to the Class file format specification; For example, whether the value starts with 0xCAFEBABE, whether the major and minor versions are within the processing range of the current VM, and whether the constants in the constant pool have unsupported types.

Metadata verification: Semantic analysis of the information described by bytecode (note: compared with the semantic analysis in the compilation phase of JavAC) to ensure that the information described conforms to the requirements of the Java language specification; For example, does this class have a parent other than java.lang.object?

Bytecode validation: Determine that program semantics are legitimate and logical through data flow and control flow analysis.

Symbol reference validation: Ensures that the parse action is performed correctly.

The validation phase is important, but not required, and has no effect on program runtime. If the referenced classes are repeatedly validated, consider using the -xVerifyNone parameter to turn off most of the class validation to shorten the virtual machine class load time.

– Preparation: Allocates memory for static variables of the class and initializes them to default values

The preparation phase is the phase that formally allocates memory and sets initial values for class variables, all of which will be allocated in the method area. There are several points to note about this phase:

Static class variables are allocated, not instance variables, which are allocated in the Java heap along with the object when it is instantiated.

2. The initial value set here is usually the default zero value of the data type (such as 0, 0L, NULL, false, etc.) rather than the value explicitly assigned in Java code.

Public static int value = 3;

The initial value of the value variable after the preparation phase is 0, not 3, because no Java methods have been executed yet, and the putStatic instruction that assigns value to 3 is stored in the class constructor () method after the program is compiled. Therefore, assigning value to 3 will only be performed during initialization.

, also need to note the following points: here, for the basic data type, for class variables (static) and global variables, if not explicitly the assignment and used directly, then the system will be given for its default of zero value, and for local variables, before use must be explicitly assign, otherwise not through at compile time. · Constants that are both static and final must be explicitly assigned when they are declared, otherwise they will not pass at compile time; A constant that is only final can be explicitly assigned at declaration time or at class initialization. In general, it must be explicitly assigned before use and will not be given a default zero value. · For reference data type, such as group reference and object reference, if it is directly used without explicit assignment, the system will give it the default zero value, namely NULL. · If the elements of the array are not assigned when the array is initialized, the elements will be assigned a default value of zero based on the corresponding data type.Copy the code

3. If a class field has a ConstantValue property in the field property table, which is both final and static, then the value variable is initialized to the value specified by the ConstValue property in the preparation phase.

Public static final int value = 3;

At compile time Javac will generate a ConstantValue attribute for value, and in preparation the vm will assign value to 3 based on the ConstantValue setting. Recall the second example of passive object references from the previous blog post. Static final constants put their results into the constant pool of the calling class at compile time

– Parse: Converts symbolic references in a class to direct references

In the parsing phase, the VIRTUAL machine replaces symbolic references in the constant pool with direct references. The parsing action is mainly performed for class or interface references, fields, class methods, interface methods, method types, method handles, and call point qualifiers. A symbolic reference is a set of symbols that describe a target, which can be any literal.

A direct reference is a pointer to a target directly, a relative offset, or a handle to the target indirectly.

Initialize the

Class initialization, which assigns correct initial values to static variables of a class. The JVM is responsible for initializing classes, mainly class variables. There are two ways to initialize a class variable in Java:

① Declare class variables to be specified initial values

② Use static code blocks to specify initial values for class variables

JVM initialization steps

1. If the class has not already been loaded and connected, the program loads and connects the class first

2. If the immediate parent of the class has not already been initialized, initialize its immediate parent first

3. If there are initializers in a class, the system executes those initializers in turn

Class initialization timing: Class initialization occurs only when a class is actively used. Active use of a class includes the following six types:

Create an instance of the class, that is, new

– Accesses or assigns a value to a static variable of a class or interface

Call a static method of a class

— Reflection (e.g. Class.forname (” com.shengsiyuan.test “))

– If a subclass of a class is initialized, its parent class is also initialized

– Java Test is the class marked as the startup class when the Java VM starts. You can run a main class using the java.exe command

End of life cycle

• The Life cycle of a Java VIRTUAL machine ends in one of the following situations

– The system.exit () method is executed

– The program is successfully executed

– The program is terminated due to an exception or error during execution

– The Java VM process is terminated due to an operating system error

Class loaders

**** find class loaders, **** start with a small example

package com.neo.classloader; public class ClassLoaderTest { public static void main(String[] args) { ClassLoader loader = Thread.currentThread().getContextClassLoader(); System.out.println(loader); System.out.println(loader.getParent()); System.out.println(loader.getParent().getParent()); }}Copy the code

After running, the output is as follows:

sun.misc.Launcher$AppClassLoader@64fef26a
sun.misc.Launcher$ExtClassLoader@1ddd40f3
null
Copy the code

The Bootstrap Loader is implemented in C language. There is no definite way to return the parent Loader, so null is returned.

The hierarchy of these loaders is shown in the figure below:

Note: The parent class loader is not implemented by inheritance, but by composition.

From a Java virtual machine perspective, there are only two different class loaders:

Startup class loader: it is implemented in C++ (this is limited to Hotspot, the default virtual machine after JDK1.5, many other virtual machines are implemented in Java) and is part of the virtual machine itself; All other classloaders: these classloaders are implemented in the Java language, independent of the virtual machine, and all inherit from the abstract java.lang.ClassLoader class, which needs to be loaded into memory by the launcher ClassLoader before it can load other classes.

From a Java developer’s point of view, class loaders can be broadly divided into three categories:

Start the classloader: The Bootstrap ClassLoader is responsible for loading libraries that are stored in JDK\jre\lib(JDK stands for JDK installation directory, the same below) or in the path specified by -xbootclasspath and recognized by the virtual machine (such as rt.jar, All classes starting with Java.* are loaded by Bootstrap ClassLoader. Startup class loaders cannot be directly referenced by Java programs.

Extended class loaders: Launcher$ExtClassLoader, which is used to load the DK\jre\lib\ext directory. Or all libraries in the path specified by the java.ext.dirs system variable (such as classes beginning with Javax.*) can be used directly by the developer.

Application class loaders: The Application ClassLoader is implemented by sun.misc.Launcher$AppClassLoader, which loads the classes specified by the user’s ClassPath. Developers can use the Application ClassLoader directly. If the application does not have its own custom class loader, this is generally the default class loader in the application.

All three types of loaders work together to load applications, and custom class loaders can be added if necessary. Since the JVM’s built-in ClassLoader only knows how to load standard Java class files from the local file system, if you write your own ClassLoader, you can do the following:

1) Automatically validate the digital signature before executing the untrusted code.

2) Dynamically create custom build classes that meet the specific needs of users.

3) Retrieve Java classes from specific locations, such as databases and networks.

JVM class loading mechanism

****•**** is responsible for everything. When a Class loader is responsible for loading a Class, other classes that that Class depends on and references are also loaded by the Class loader, unless it is shown to be loaded using another Class loader

****•**** parent delegate, which first lets the parent loader try to load the class, and only tries to load the class from its own classpath if the parent loader fails to load the class

****•**** Cache mechanism. The cache mechanism ensures that all loaded classes are cached. When a program needs to use a Class, the Class loader first searches for the Class in the cache. Is that why you have to restart the JVM to make Class changes to take effect

4. Class loading

There are three ways to load a class:

1. The command line startup application is initialized by the JVM

2. Load dynamically through class.forname ()

3. Use the classloader.loadClass () method to load dynamically

Example:

package com.neo.classloader; public class loaderTest { public static void main(String[] args) throws ClassNotFoundException { ClassLoader loader = HelloWorld.class.getClassLoader(); System.out.println(loader); Loader.loadclass () is used to load classes without executing the initialization block loader.loadClass("Test2"); // Use class.forname () to load classes, default initialization block is executed // class.forname ("Test2"); // Class. ForName ("Test2", false, loader); // Class. ForName ("Test2", false, loader); }}Copy the code

Demo class

Public class Test2 {static {system.out. println(" Static initialization block executed! ") ); }}Copy the code

If you switch the loading mode, different output results are displayed.

Class.forname () and classLoader.loadClass ()

Class.forname () : In addition to loading the Class’s.class file into the JVM, the Class is interpreted, executing the static block of the Class;

Classloader.loadclass () : does only one thing: loads a. Class file into the JVM. Static blocks are executed only at newInstance.

Note:

Class. ForName (name, initialize, loader) functions with parameters can also control whether static blocks are loaded. And only the newInstance() method is invoked to create objects of the class using the call constructor.

5. Parental delegation model

The workflow of the parental delegation model is as follows: If a class loader received the request of the class loading, it won’t try to load the first class, but give parent to complete the request, in turn up, as a result, all of the class loading request should be passed to the top finally start the class loader, only when the parent loader in the scope of its search did not find the required class, is unable to complete the loading, The child loader will try to load the class itself.

Parent delegate mechanism:

1. When an AppClassLoader loads a class, it does not attempt to load the class itself. Instead, it delegates the request to the parent class loader, ExtClassLoader.

2. When ExtClassLoader loads a class, it does not attempt to load the class itself in the first place. Instead, it delegates the class loading request to BootStrapClassLoader.

3. If the BootStrapClassLoader fails to load (for example, the class cannot be found in $JAVA_HOME/jre/lib), the ExtClassLoader will be used to try loading.

4. If the ExtClassLoader also fails to load, AppClassLoader will be used to load the ExtClassLoader. If the AppClassLoader also fails to load, ClassNotFoundException will be reported.

ClassLoader source code:

public Class<? > loadClass(String name)throws ClassNotFoundException { return loadClass(name, false); } protected synchronized Class<? > loadClass(String name, Boolean resolve)throws ClassNotFoundException {// First check whether the type has been loaded Class c = findLoadedClass(name); If (c == null) {// If not loaded, delegate to the parent class load or delegate to the start class loader load try {if (parent! C = parent.loadClass(name, false); } else {// If there is no parent class loader, check if the class was loaded by the starting class loader, Native Class findBootstrapClass(String name) c = findBootstrapClass0(name); }} catch (ClassNotFoundException e) {c = findClass(name);}} Catch (ClassNotFoundException e) {c = findClass(name); } } if (resolve) { resolveClass(c); } return c; }Copy the code

Significance of parental delegation model:

– The system class prevents multiple copies of the same bytecode from appearing in memory

– Ensure the secure and stable running of Java programs

6. Custom class loaders

Normally, we use the system class loader directly. However, there are times when custom class loaders are also needed. For example, an application transmits Java class bytecodes over the network. To ensure security, the bytecodes are encrypted. In this case, the system class loader cannot load the bytecodes. Custom classloaders are generally inherited from classloaders, so we just need to override the findClass method. Here’s an example to illustrate the process of customizing a class loader:

package com.neo.classloader; import java.io.*; public class MyClassLoader extends ClassLoader { private String root; protected Class<? > findClass(String name) throws ClassNotFoundException { byte[] classData = loadClassData(name); if (classData == null) { throw new ClassNotFoundException(); } else { return defineClass(name, classData, 0, classData.length); } } private byte[] loadClassData(String className) { String fileName = root + File.separatorChar + className.replace('.', File.separatorChar) + ".class"; try { InputStream ins = new FileInputStream(fileName); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; int length = 0; while ((length = ins.read(buffer)) ! = -1) { baos.write(buffer, 0, length); } return baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); } return null; } public String getRoot() { return root; } public void setRoot(String root) { this.root = root; } public static void main(String[] args) { MyClassLoader classLoader = new MyClassLoader(); classLoader.setRoot("E:\\temp"); Class<? > testClass = null; try { testClass = classLoader.loadClass("com.neo.classloader.Test2"); Object object = testClass.newInstance(); System.out.println(object.getClass().getClassLoader()); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); }}}Copy the code

The core of the custom class loader is the retrieval of the bytecode file, which needs to be decrypted in the class if it is encrypted bytecode. Since this is just a demonstration, I have not encrypted the class file, so there is no decryption. Here are a few things to note:

1, pass the filename here need to be a class defining all name, namely com. Paddx. Test. The classloading. Test format, because defineClass method is according to the process of this format.

2. It is best not to overwrite the loadClass method, as this can easily break the parent delegate pattern.

3, this kind of Test class itself can be AppClassLoader class loading, so we can’t put the com/paddx/Test/classloading/Test. The class under the class path. Otherwise, the parent delegate mechanism will cause the class to be loaded by the AppClassLoader rather than by our custom class loader.

Information recommendation

Recently caught up with job-hunting peak season (recruitment season), a lot of readers have asked me to have the latest interview questions, find huawei friends to sort out an internal data “6th edition: Internet big factory interview questions” and classified 4 PDF, a total of 926 pages!

The entire information package, Includes Spring and Spring Boot/Cloud, Dubbo, JVM, collection, multithreading, JPA, MyBatis, MySQL, big data, Nginx, Git, Docker, GitHub, Servlet, JavaWeb, IDEA, Redis, algorithm, interview questions and so on almost cover Java Basic and alibaba and other big factory interview questions, such as technology stack!

It is said that some friends have successfully joined ant Financial, Bytedance and other big companies through this information.

Moreover, these materials are not scanned version, the text inside can be directly copied, very convenient for us to learn: