JVMClass loader

[JVM] Class Loader

Article directory

  • 【JVM】Class loader
    • 0. Class loader overview
    • 1. Classification of class loaders
      • 1.1 Start the class loader
      • 1.2 Default class loader in Java
        • 1.2.1 Extension class loader
        • 1.2.2 Application class loader
    • 2. Parental delegation mechanism
      • What is the parent delegation mechanism for 2.1 classes?
      • 2.2 Breaking the parental delegation mechanism
        • 2.2.1 Custom class loader
        • 2.2.2 Thread context class loader
      • 2.3 OSGi modularization
    • 3. Summary

0. Class loader overview

ClassLoader is a technology provided by the Java virtual machine to applications to obtain class and interface bytecode data.
image-20231025141442943
image-20231025141442943

1. Classification of class loaders

Class loaders are divided into two categories:

  1. Class loader implemented in Java code
  2. Class loader implemented by JVM underlying source code

image-20231025141442943

The design of class loaders in jdk8 and later versions is quite different. The default class loaders in jdk8 and previous versions are as follows:

  1. JVM underlying implementation (C++):
    • Start the class loader Bootstrap: load the core classes in Java
  2. Java:
    • Extension class loader Extension: allows extending more common classes in Java
    • Application class loader Application: loads classes used by the application

1.1 Start the class loader

**Bootstrap ClassLoader** is a class loader provided by the Hotspot virtual machine and written in C++. Class files in the Java installation directory/jre/lib are loaded by default, such as rt.jar, tools.jar, resources.jar, etc.

There are two ways to use the startup class loader to load user jar packages:

  1. Put the jar package into the jre/lib directory for expansion
    • It is not recommended. Try not to change the contents of the JDK installation directory, because even if the jar package is placed in this directory, the jar package may not be loaded normally due to file name mismatch.
  2. Expand with parameters
    • It is recommended to use -Xbootclasspath/a:path/jar package name.jar for expansion.

1.2 Default class loader in Java

Extension class loader and Application class loader both refer to the class loaders provided in the JDK and written in Java. Their source code is located in sun.misc.Launcher, which is a static internal class. Inherited from URLClassLoader, you can load bytecode files into memory through a directory or specified jar package.

image-20231025164359439

1.2.1 Extension class loader

**Extension ClassLoader** is a class loader provided in jdk and written in Java. Class files in the Java installation directory /jre/lib/ext are loaded by default.

How to load user jar packages by extending the class loader:

  1. Put it under jre/lib/ext for expansion.
    • Not recommended, try not to change the contents of the jdk installation directory.
  2. Expand with parameters
    • It is recommended to use -Djava.ext.dirs=jar package directory for expansion. This method will overwrite the original directory. We should use ; (windows) or : (macos/linux) appends the original directory.
1.2.2 Application Class Loader

Application Class Loader (AppClassLoader): A loader for our users, responsible for loading all jar packages and classes under the current application classpath.

2. Parental delegation mechanism

Since there are multiple class loaders in the JVM, the core of the parent delegation mechanism is to solve the problem of who loads a class.

The role of the parent delegation mechanism:

  1. Ensure the security of class loading: Use the parental delegation mechanism to prevent malicious code from replacing the core class library in jdk, such as java.lang.String, to ensure the integrity of the core class library and security.
  2. Avoid repeated loading: The parent delegation mechanism can prevent the same class from being loaded multiple times.

The parent delegation mechanism refers to: when a class loader receives the task of loading a class, it will search from the bottom up to see if it has been loaded, and then load it from the top down.
image-20231025141442943

  1. Find up:
    • If the upward search has already been loaded, the Class object will be returned directly and the loading process will end. This will avoid repeated loading of a class.
  2. Loading down:
    • If all parent class loaders fail to load the class, the current class loader attempts to load it itself. So it looks like a top-down attempt.
    • The second time you load the same class, it will still be delegated upwards. If a class loader has loaded it, it will return directly.

Each class loader implemented in Java stores a class loader with a member variable named parent, which can be understood as its superior, not an inheritance relationship. **The parent class loader of the application class loader is the extension class loader, and the parent of the extension class loader is empty because the startup class loader is implemented in C++ and cannot be obtained in Java.

2.1 What is the parent delegation mechanism for classes?

What is the parent delegation mechanism for classes?

  1. When a class loader loads a certain class, it will search from the bottom up to see if it has been loaded. If it has been loaded, it will directly return the Class object. If it has not been loaded until the top class loader, it will continue from the top down. load.
  2. The parent class loader of the application class loader is the extension class loader, and the parent class loader of the extension class loader is the startup class loader.
  3. Benefits of the parent delegation mechanism:
    • Avoid malicious code from replacing the core class library in jdk to ensure the integrity and security of the core class library.
    • Avoid classes being loaded repeatedly.

2.2 Breaking the parental delegation mechanism

Three ways to break parental delegation:

  1. Custom class loader: Customize the class loader and override the loadClass method to remove the code of the parental delegation mechanism.
  2. Thread context class loader: Use the context class loader to load classes, such as JDBC and JNDI.
  3. OsgiClass loader of the framework: Historically, the Osgi framework implemented a new class loader mechanism that allowed the loading of classes to be delegated between peers.
2.2.1 Custom class loader
  • A Tomcat program can run multiple Web applications. If a class with the same qualified name appears in the two applications, such as the Servlet class, Tomcat must ensure that both classes can be loaded and they should be different classes.
  • If the parental delegation mechanism is not broken, after the application class loader loads MyServlet in Web application 1, the MyServlet class with the same qualified name in Web application 2 cannot be loaded.
    image-20231025141442943

Tomcat uses a custom class loader to isolate classes between applications. Each application will have a separate class loader added to the corresponding class.
image-20231025141442943

ClassLoader contains 4 core methods (the core code of the parent delegation mechanism is located in the loadClass method):
image-20231025141442943

The key to breaking the parental delegation mechanism is to override the logic in the loadClass method.

2.2.2 Thread context class loader

JDBC uses DriverManager to manage the drivers of different databases introduced in the project, such as mysql driver and oracle driver.
image-20231025141442943

The DriverManager class is located in the rt.jar package and is loaded by the startup class loader. The class corresponding to the mysql driver in the dependency is loaded by the application class loader. This violates the parental delegation mechanism.
image-20231025141442943

DriverManager uses the SPI mechanism to finally load the corresponding driver class in the jar package.
image-20231025141442943

So how does the SPI mechanism obtain the application class loader?

SPI uses the class loader saved in the thread context to load classes. This class loader is generally the application class loader.

public static <S> ServiceLoader<S> load(Class<S> service){<!-- -->
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    return ServiceLoader.load(service,cl);
}

Complete process:

  1. Start the class loader to load DriverManager
  2. When initializing DriverManager, load the mysql driver in the jar package through the SPI mechanism
  3. SPI uses the thread context class loader (application class loader) to load classes and create objects.

Think:

Did the JDBC case really break the parental delegation mechanism?

There are two ways to say it:

  1. Breaks the parent delegation mechanism: This method delegates application class loader to load classes loaded by startup class loader. Breaking the parental delegation mechanism.
  2. No violation of the parental delegation mechanism: There is no violation of the parental delegation mechanism during the class loading process. Because DriverManager is located under the rt.jar package and is loaded by the Startup Class Loader, while the mysql driver is located on the classpath and is loaded by the Application Class Loader ,no problem.

2.3 OSGi modularization

Historically, OSGi modular framework. It exists delegated loading of class loaders between peers. OSGi also uses class loaders to implement the function of hot deployment (dynamically updating bytecode files into memory without stopping the service).

image-20231025224629529

3. Summary

  1. What is the role of a class loader?

Answer: The class loader (ClassLoader) is responsible for obtaining the bytecode during the class loading process and loading it into memory and converting it into byte[]. Then it calls the underlying method of the virtual machine to convert the byte[] into data in the method area and heap.

  1. How many common class loaders are there?

answer:

  • Start the class loader: load core classes
  • Extension class loader: loads extension classes
  • Application class loader: loads classes in the application classpath
  • Custom class loader: override findClass method
  1. What is parent delegation?

Answer: Each class loader implemented in Java stores a class loader with a member variable called parent. Check whether it has been loaded from the bottom up, and then load it from the top down. This avoids the problem of core classes being rewritten and overwritten by applications, improving security.
image-20231025141442943

  1. How to break the parental delegation mechanism?

answer:

  1. Override the loadClass method.
  2. Frameworks such as JNDI, JDBC, JCE, JAXB and JBIuse the SPI mechanism + thread context class loader.
  3. OSGi implements a set of class loading mechanisms thatallow class loaders of the same level to call each other.