tomcat 双亲委托机制

发布时间 2023-04-13 16:57:19作者: vx_guanchaoguo0

tomcat 著名的双亲委托机制

  • 就是有类需要加载时就委托父类去加载 一直到顶级的 Bootstrap 都没有自己才加载 ,自己也没有就报错

类加载器

  1. Bootstrap ClassLoader:JVM内置的类加载器,用来加载Java核心类库,例如rt.jar、resources.jar等等。
  2. Extension ClassLoader:用来加载Java扩展类库,例如jre/lib/ext目录下的jar包。
  3. Common ClassLoader:主要用于加载Tomcat共享的类库,例如Tomcat中的servlet-api.jar和jsp-api.jar等,这些类库被所有的Web应用程序共享,因此需要通过一个公共的类加载器来加载
  4. System ClassLoader:也称为应用程序类加载器(Application ClassLoader),用来加载系统类和应用程序类,例如用户自定义的类和第三方库中的类。
  5. WEB Application ClassLoader:Web应用程序创建一个独立的类加载器,这样可以保证每个Web应用程序之间的类和资源相互隔离,互不干扰。

什么情况需要打破双亲委托机制

  • 每个web Application 依赖的上级类名称一致但是版本不一样

如何打破双亲委托机制

  • 继承URLClassLoader或者ClassLoader类,然后重写loadClass()方法
  • 自己加载时就从自己路劲加载 没有时候就从父类加载 super.loadClass()
实例代码
public class CustomClassLoader extends ClassLoader {
    private String classPath;

    public CustomClassLoader(String classPath) {
        this.classPath = classPath;
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            // 首先尝试从自定义的类路径中加载类
            Class<?> c = findClass(name);
            if (c != null) {
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }

            // 如果自定义的类路径中不存在该类,则调用父类加载器进行加载
            return super.loadClass(name, resolve);
        }
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 从指定路径或者jar包中加载类
        byte[] classBytes = loadClassBytes(name);
        if (classBytes == null) {
            throw new ClassNotFoundException(name);
        }

        // 定义类
        Class<?> c = defineClass(name, classBytes, 0, classBytes.length);
        if (c == null) {
            throw new ClassNotFoundException(name);
        }

        return c;
    }

    private byte[] loadClassBytes(String name) {
        // 实现从指定路径或者jar包中加载类文件的逻辑
        // 省略具体实现细节
    }
}