自定义类加载如何打破双亲委托机制的正确姿势

通过自定义类加载打破类加载双亲规则

@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    Class<?> clazz = findLoadedClass(name);
    try{
        if(clazz == null) clazz = findClass(name);
    }catch (ClassNotFoundException e){
        // ClassNotFoundException thrown if class not found
        // from the non-null parent class loader
    }

    if(clazz == null && getParent() != null){
        clazz = getParent().loadClass(name);
    }

    if(resolve){
        resolveClass(clazz);
    }
    return clazz;
}

  其中clazz = findClass(name);必须catch,尽管loadClass也抛出了ClassNotFoundException异常,因为我们现在要实现的是,自定义类加载器加载不到(也就是找不到这个类),就让自定义加载器的父加载器(ApplicationClassLoader)去加载,如果你这里将异常抛出了,父加载器根本没有机会去加载。那么什么时候自定加载器加载不到呢,这个问题就在findClass(name)里,看你是怎么实现的findClass了。如:

/**
     * 这是查找非classpath下的类(自定义目录),并未打破双亲规则
     * @param name
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
//        String className = name.substring(name.lastIndexOf("."));
//        name.substring(0, name.lastIndexOf("."));
        String classPath = dir + File.separator + name.replace(".", "\\") + ".class";

//        File classFile = new File(dir, classPath);
        File classFile = new File(classPath);
        if(!classFile.exists()){
            throw new ClassNotFoundException("this class "+ classPath +" is not found under [" + dir + "]");
        }

        byte[] classBytes = loadClassBytes(classFile);//通过class文件获取数组
        if(null == classBytes || classBytes.length == 0)
            throw new ClassNotFoundException("load this class is failed");

        //这样还是加载不到java.*的类,因为在ClassLoader里面是写死的
        Class c = AccessController.doPrivileged(new PrivilegedAction<Class>() {
            @Override
            public Class run() {
                return defineClass(name, classBytes, 0, classBytes.length);
            }
        });

        System.out.println("find class successfully");
        return c;
    }

  如上,在自定义目录(非classpath)下找不到这个你这个类名指定的class文件,就会抛出ClassNotFoundException异常,所以像java.*包里的类,自定义加载器是加载不到的(就算有这个文件,也加载不到),所以这时就需要父加载器去加载了,ClassNotFoundException也由父加载器去抛出。注意从父加载器开始,还是满足双亲委托机制的。

  最后说明一下,其实tomcat类加载机制并未打破类双亲委托机制,它只是没有classpath的概念,然后加载的类是从自定义目录里去加载的,所以才会去实现自定义加载器。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值