Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article also participated in the “Digitalstar Project” to win a creative gift package and creative incentive money

Code shrimp is a sand carving and funny boy who likes listening to music, playing games and writing as well as most of his friends. The days are still very long, let’s refuel our efforts together 🌈


🔥 Foreword — > Featured column

Self-introduction, to everyone recommend their column 😁, welcome small partners to collect attention 😊

Force link algorithm problem solving area

The small white to learn Java

MybatisPlus column

App crawler Column

PC side crawler column

Big factory interview question column


What is the parent delegate mechanism?

When it comes to parental delegation, we need to know about class loaders in Java!

🌊Java class loaders are classified into the following four categories:

  1. Start the BootStrap ClassLoader, which is responsible for loading the bytecode files related to jre/lib/rt.jar.

  2. Extension ClassLoader, mainly load jre/lib/ext/*.jar jar packages.

  3. The Application ClassLoader is responsible for loading user-defined classes and jar packages configured by the classpath environment variable.

  4. Custom class loader (UserClassLoader) is responsible for loading bytecode files in a special directory specified by the programmer. In most cases, custom classloaders simply inherit the ClassLoader abstract class and override the findClass() and loadClass() methods.

Principle of parental delegation mechanism

  1. If a classloader receives a classload request, it does not load the request itself. Instead, it delegates the request to the parent class’s loader.
  2. If the parent class’s loader also has a parent class loader, then further delegate up and recursive requests eventually reach the top-level start class loader.
  3. If the parent class loader can complete the task, it returns successfully. If the parent class loader cannot complete the task, the child loader will try to load itself. This is the parent delegate mechanism.

advantages

  1. Avoid reloading classes
  2. Protect program security and prevent the core API from being tampered with

disadvantages

  • Parental delegation can be too limiting in some scenarios, so it is sometimes necessary to break the parental delegation mechanism to achieve this goal. For example, the SPI mechanism



Break the parental delegation mechanism?

Break the parental delegation mechanism?

Friend: I think the parent delegation mechanism is very good, why break it?

Mantis shrimp: Ha ha, then directly on the example explained ba. 😉


Prerequisite knowledge: Thread context classloader

The Thread Context Class Loader was introduced in JDK 1.2. The methods getContextClassLoader() and setContextClassLoader(ClassLoader CL) in java.lang.Thread are used to get and set the context ClassLoader for the Thread. If not set by the setContextClassLoader(ClassLoader CL) method, the thread inherits its parent thread’s context ClassLoader.

The context class loader of the initial thread in which a Java application runs is the application class loader, through which code running in the thread can load classes and resources.

The thread-context class loader fundamentally solves the problem that common applications cannot violate the parental delegation pattern, making the Java class loading system more flexible. The problems mentioned above are the forte of thread-context classloaders. The thread context classloader for A Java application is the system classloader by default if no Settings are made. Therefore, using a thread-context class loader in SPI interface code can successfully load classes implemented by SPI.


Before parental delegation

Due to theThe parental delegation model was introduced after JDK1.2Before that, there were user-defined class loaders. So, these are not following the parental delegation principle.

To load a class, you need to inherit the ClassLoader and override findClass. If you don’t want to break the parent delegate model, you just need to override findClass. If you want to break the parent-delegate model, rewrite the entire loadClass method and set your own class-loading logic


JDBC breaks the parent delegate mechanism

Create database links using the SPI mechanism

As long as the mysql JAR package is in the classpath.

Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql"."root"."0000");
Copy the code

DriverManager is loaded by the class loader before the code is executed, because the java.sql.DriverManager class is underneath rt.jar, so it is loaded by the startup class loader.

When a class is loaded, static methods of the class are executed. One key piece of code is:

ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Copy the code

This code will attempt to load any implementation classes under the classpath that implement the Driver interface.

So, here’s the problem.

DriverManager is loaded by the startup class loader, so when the above code is encountered during loading, it will try to load all the Driver implementation classes, but these implementation classes are provided by a third party, and the third party classes cannot be loaded by the startup class loader.

So, how to solve this problem?

Thus, the use of application classloaders in JDBC by introducing ThreadContextClassLoader (thread context loader, by default AppClassLoader) breaks the parent delegate principle.

If we dig into the Serviceloader.load method, we can see:

public static <S> ServiceLoader<S> load(Class<S> service) {
    // Get the thread context class loader
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    return ServiceLoader.load(service, cl);
}
Copy the code

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.

If you use the default parent delegate class loading mechanism, you cannot load multiple identical classes.

Therefore, Tomcat breaks the parent delegate principle and provides a separate WebAppClassLoader for each Web container by providing a mechanism for isolation.

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.

CommonClassLoader, CatalinaClassLoader, SharedClassLoader, and WebappClassLoader are class loaders defined by Tomcat. They load Java libraries in /common/, /server/, /shared/* (merged into the root lib directory after Tomcat 6), and /WebApp/WEB-INF/*, respectively.

There are usually multiple instances of WebApp classloader and Jsp classloader. Each Web application corresponds to a WebApp classloader, and each Jsp file corresponds to a Jsp classloader.


How to break parental delegation?

1. Custom class loaders

To load a class, you need to inherit the ClassLoader and override findClass. If you don’t want to break the parent delegate model, you just need to override findClass. If you want to break the parent-delegate model, rewrite the entire loadClass method and set your own class-loading logic

If you want to break it, you want to load it by yourself and not by the parent loader

2. Use the thread context class loader

public class Main {

    public static void main(String[] args) { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); }}Copy the code



💖 finally

I am aCode pipi shrimp, a prawns lover who loves to share knowledge, will update useful blog posts in the future, looking forward to your attention!!

Creation is not easy, if this blog is helpful to you, I hope you can == one key three even oh! Thank you for your support. See you next time