动态修改当前ClassLoader

自定义ClassLoader相信很多人都用过,网上文章也有很多。但如何使用自定义的ClassLoader有时确实比较头痛。

如果启动入口自己可以控制还好说,大不了通过自定义ClassLoader加载所有类就可以了,但如果控制不了,比如说是通过TOMCAT或脚本来启动的,但又要用自定义的ClassLoader来加载外部类,那就郁闷了。


我碰到的情形就是如此,其中的ClassLoaderC是tomcat的类加载器,而classLoaderD是自定义的类加载器。通常来说,我们只能选择访问C或D其中一个下面的类。有没办法能同时访问它们下两个的类呢?

 

其中一种办法是Thread.currentThread().setContextClassLoader。相对比较方便,但这在多线程环境下很容易产生问题。

还有一种办法是通过反射调用,修改ClassLoaderC的parent为ClassLoaderD。我们知道ClassLoader的委托机制是先让parent(父)类加载器寻找,只有在parent找不到的时候才从自己的类路径中去寻找。这样我们通过修改parent就能达到同时访问的目的。当然,由于parent是私有的,而且没有提供写方法,所以还需要用反射来设置。

 

之前还尝试了另一种方法,即ClassLoader.addClass,但发现类是进去了,但package里没有,还是会加载不到类。

 

这种方法目前还在试用,大家觉得有什么问题欢迎提出来:)

 

 

public class ContainerClassLoader extends ClassLoader {

    private Map<String, Class<?>> loadedClasses = new HashMap<String, Class<?>>();

    private static ContainerClassLoader INSTANCE;

    private ContainerClassLoader() {
        super(ContainerClassLoader.class.getClassLoader().getParent());
    }

    /**
     * 初始化
     */
    public static void init() {
        INSTANCE = new ContainerClassLoader();
        try {
            INSTANCE.addThisToParentClassLoader(ContainerClassLoader.class
                    .getClassLoader());
        } catch (Exception e) {
            System.err.println("设置classloader到容器中时出现错误!");
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
        if (loadedClasses.containsKey(name)) {
            return loadedClasses.get(name);
        }
        return super.loadClass(name, resolve);
    }

    /**
     * 将this替换为指定classLoader的parent ClassLoader
     * 
     * @param classLoader
     */
    private void addThisToParentClassLoader(ClassLoader classLoader) throws Exception {
        Field field = ClassLoader.class.getDeclaredField("parent");
        field.setAccessible(true);
        field.set(classLoader, this);
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值