java双亲委派机制,以及如何打破双亲委派

1,什么是双亲委派机制,为什么要用这种机制

"向上委派"和"向下查找"是指类加载器在加载Java类时的一种机制。

"向上委派"指的是当一个类加载器需要加载某个类时,它会先请求其父类加载器去尝试加载该类。如果父类加载器无法加载该类,再由当前类加载器自己进行加载。

"向下查找"则相反,指的是当一个类被加载时,在其中需要引用其他类时,会由当前类加载器首先尝试去加载这些类,如果无法加载,则会交由其子类加载器去尝试加载。

通过这种机制,每个类加载器都优先向上委派请求父类加载器来尝试加载类,而且若父类加载器已经成功加载了某个类,子类加载器就不会再次加载,从而避免重复加载,提高了加载效率。同时,当需要查找某个类时,也可以通过向下查找的方式快速定位到对应的类。

2,tomcat为什么要违反双亲委派规则

Tomcat为了实现Web应用程序的隔离和独立性,采用了自定义类加载器来加载Web应用程序中的类文件。在这个过程中,如果Web应用程序包含重复的类文件,则Tomcat会根据其自己的查找规则加载这些类,而不是采用Java标准的双亲委派机制。

这种做法的主要原因是,每个Web应用程序都有自己的类文件和依赖项,如果采用传统的父子层次关系进行加载,则可能会导致冲突和错误。例如,如果两个Web应用程序都使用了相同版本的JAR文件,但其中一个应用程序使用了修订版的JAR文件,那么使用传统的双亲委派机制将无法处理这种情况,并且可能会导致类冲突和错误。

Tomcat使用的自定义类加载器可以根据一定的规则先从本地的WEB-INF/classes目录和WEB-INF/lib目录下查找类文件,如果没有找到,则再由其父类加载器(通常是系统类加载器)进行查找。这样就可以避免类名冲突和错误,并确保每个Web应用程序都能够在独立的环境中运行。
以下是Tomcat Web应用程序类加载器的示例代码:

public class WebappClassLoader extends URLClassLoader {
    private static final String[] TRIGGERS = {"org.apache.catalina.", "org.apache.tomcat."};

    public WebappClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
    }

    @Override
    protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        // 检查类是否已经被加载
        Class<?> c = findLoadedClass(name);
        if (c != null) {
            return c;
        }

        // 检查是否是系统类
        for (String trigger : TRIGGERS) {
            if (name.startsWith(trigger)) {
                // 系统类
                return super.loadClass(name, resolve);
            }
        }

        // 查找WEB-INF/classes和WEB-INF/lib目录下的类文件
        try {
            URL url = findResource(name.replace('.', '/') + ".class");
            if (url != null) {
                byte[] bytes = getBytes(url);
                c = defineClass(name, bytes, 0, bytes.length);
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }
        } catch (IOException e) {
            // 忽略
        }

        // 如果还是没有找到,交给父类加载器进行加载
        return super.loadClass(name, resolve);
    }
}

在这个例子中,WebappClassLoader类继承了URLClassLoader,并重写了loadClass方法。在loadClass方法中,先检查所加载的类是否已经被加载过,如果没有则检查是否为系统类,如果是则交由父类加载器进行加载;否则(即不是系统类)再根据自己的规则查找WEB-INF/classes和WEB-INF/lib目录下的类文件。如果还没有找到,则交由父类加载器进行加载。这样就实现了自定义的类加载;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

见未见过的风景

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值