What is a class loader?

When a Java program starts up (or is running), the JVM (Java Virtual Machine) finishes loading the classes, The first step is to use the classLoader\color{red}{classLoader} classLoader to load the binary stream (.class file) into memory.

Class loaders are a key tool for loading class files.

When is class loading triggered?

The Java VIRTUAL machine does not enforce when classes must be loaded, but it does require them to be loaded before they need to be initialized. (The JVM does not load all classes at startup because that would take up too much space in the method area. It basically loads at the point of use.)

So you can think of class initialization as the trigger point for class loading. Color {green} class initialization is the trigger point for class loading

The Java virtual machine specifies that a class must be initialized immediately if there are five and only five of the following \color{green}{five} conditions:

  1. When the virtual machine is started after the user specifies the main class that contains the main method

  2. Instantiation of the class must be triggered when the class is instantiated using the new keyword, when static fields of the class are read or written, or when static methods of the class are called

  3. When a reflection call is made to a class using reflection, if the class is not initialized, its initialization must be triggered first

  4. Initialize a class whose parent has not been initialized before

  5. In later versions of JDK7 using dynamic language support, Java. Lang. Invoke. Analytical result is REF_getStatic MethodHandle instance, REF_putStatic, REF_invokeStatic method handles, Instantiation must be triggered before the class corresponding to the handle is initialized

What class is the same class?

Java has two conditions for determining whether two classes are the same class

  1. The full name of the class is the same (i.e., package full path + class name)

  2. The class loader is the same

What are class loaders?

For routine use, we don’t need to worry about classloaders; the JVM has three built-in classloaders for our daily needs.

The built-in class loaders go from top to bottom, starting the class loaders -> extending class loaders -> application class loaders

If you need to load your own classes, Java supports custom class loaders to do so

Scope of different class loaders

Since there are three different class loaders built into the JVM, it is obvious that each of them has its own job

Chinese English Scope of Function (Responsibilities)
Start the class loader Bootstrap ClassLoader Jar, resources. Jar, charsets. Jar and class in %JRE_HOME%\lib
Extend the class loader Extention ClassLoader Load jar packages and class files in %JRE_HOME%\lib\ext
Application class loader Application ClassLoader It is responsible for loading all classes in the current application’s classpath
Custom class loaders User ClassLoader User-defined class loader that can load a class file in a specified path
As you can see, different classloaders do their job by loading.class files in different paths.Copy the code


Be aware of the application class loader . This is how we load all our own class files Color {red}{note the application class loader, which loads all our own class files}

How do class loaders work together?

Limit the loading range and everything will be fine?

Scoping provides some assurance that classes will not be reloaded, but not in either case

  1. If the class loaders are flat, the content they load loses its hierarchical relationship, and the problem of reloading is unavoidable once the same content appears in different paths

  2. For security reasons, Java’s own system classes cannot be loaded arbitrarily, and must be loaded by the specified class loader rather than by the user

Parent delegation mechanism

To solve these two problems, the JVM runs in parent-delegate mode, in addition to limiting the loading range of different class loaders.

The parent delegate mechanism means that when a class loader receives a request for a class load, it does not load the specified class directly, but delegates the request to its parent. The current loader is responsible for loading the class only if the parent loader is unable to load the class.

Advantages of limited scope:

  1. User-written classes are not loaded by the start and extension class loaders

  2. Core API classes are loaded by the launcher class loader or extension class loader, which ensures security

  3. Physically isolated ranges do not subjectively reload

Advantages of parental delegation:

  1. Reloading of classes can be avoided. When the parent loader has already loaded a class, the child loader will not reload the class.

  2. Security is ensured. Since Bootstrap ClassLoader only loads classes in jar packages in JAVA_HOME, such as java.lang.Integer, this class will not be replaced unless someone runs into your machine and destroys your JDK.

Why are they called parents?

By default, the user’s own classes are loaded through the application class loader. Before the application class loader is loaded, the user will try to load through the startup class loader and the extension class loader. It is equivalent to two fathers loading first, so it is called the parent

Are class loaders inherited?

Parental delegation indicates a hierarchy and priority relationship, not inheritance

Flowchart of the parent delegation mechanism

The class loader uses the loadClass method to load the class (the loadClass method is not overridden process).

Check to see if the class has already been loaded

2. If there is no load, call the loadClass() method of the parent loader to load

3. If the parent loader is empty, the startup class loader is used as the parent loader by default.

4. If the parent class fails to load, throw a ClassNotFoundException and call your own findClass() method to load it.

Core method analysis

loadClass()

Class loading method entry, the default implementation of the parent delegate mechanism

findClass()

Load. Class bytecode by name or location, responsible for locating and finding specific. Class files

defineClass()

Converts a binary stream (bytecode) into a Class object

Custom class loaders

Java itself has three classloaders that are sufficient for everyday use, but the JVM provides the first step in allowing users to customize class loaders to control class loading, which in this way provides a lot of flexibility to implement some of the requirements

Example of a custom classloader that breaks parental delegation

Such applications need to override the loadClass() method

  1. Operating environment isolation.

tomcat:

Tomcat is a Web container, so a Single Web container may require multiple applications to be deployed.

Different applications may rely on different versions of the same third-party library, but the full pathname of a class in the library may be the same.

For example, multiple applications rely on Hollis. jar, but application A needs to rely on version 1.0.0, while application B needs to rely on version 1.0.1. One of the classes in both versions is com.Hollis.test.class.

Tomcat class loading mechanism: In order to achieve isolation, classes defined by the Web application are loaded first. Therefore, the convention of parental delegation is not followed. Each application’s own class loader — WebAppClassLoader is responsible for loading the class files in its own directory. This is the opposite of parental delegation.

  1. Hot update

A class can only be loaded once in the JVM, and if you want to load the class again, you can only load it through a new classloader, with each instantiated object pointing to the new class. When the class file of this class changes, a newer class is created again, and if the system makes a second instantiation request, the created object points to the new class.

See hot update Principles for details

Example of a custom classloader that does not break parental delegation

Just override the findClass() method

(1) Encryption: Java code can be decompiled easily. If you need to encrypt your code to prevent decompilation, you can encrypt the compiled code with some encryption algorithm. After class encryption, you can no longer use Java ClassLoader to load the class. And then load again.

(2) Load code from nonstandard sources: If your bytecode is in a database or even in the cloud, you can customize class loaders to load classes from specified sources.