ClassLoading$ChainedClassLoader与ClassLoaders$AppClassLoader的区别及获取方法
ClassLoading$ChainedClassLoader 与 ClassLoaders$AppClassLoader 的区别
1. 归属与核心定位
ClassLoaders$AppClassLoader:这是JDK原生的应用类加载器,属于JVM标准类加载器体系的一员,负责加载classpath下的应用代码和第三方依赖包,是Java程序默认使用的类加载器之一。ClassLoading$ChainedClassLoader:这是框架自定义的链式类加载器(常见于Spring Boot等框架),不属于JVM原生体系,核心是把多个类加载器串成链,按顺序尝试加载类,用来实现灵活的类加载策略。
2. 加载机制差异
ClassLoaders$AppClassLoader:严格遵循JVM的双亲委派模型,先把加载请求交给父加载器(扩展类加载器),父加载器加载失败后才会自己尝试加载。ClassLoading$ChainedClassLoader:一般不严格遵循双亲委派,而是按照自身维护的类加载器链顺序逐个尝试加载,比如先调用链中第一个类加载器,失败就轮到下一个,直到遍历完整个链。
3. 适用场景
ClassLoaders$AppClassLoader:日常Java开发中绝大多数类都是通过它加载的,是应用程序类加载的默认选择。ClassLoading$ChainedClassLoader:主要用于类隔离、多版本依赖共存的场景,比如模块化应用中,需要让不同模块用不同类加载器加载依赖时,通过链式组合来实现灵活的类加载逻辑。
如何获取 ClassLoading$ChainedClassLoader?
- 从框架上下文获取
如果是在使用该类的框架环境(比如Spring Boot)里,通常可以从应用上下文直接拿到:
// 示例:Spring环境下获取 ClassLoader classLoader = applicationContext.getClassLoader(); if (classLoader instanceof ClassLoading.ChainedClassLoader) { ClassLoading.ChainedClassLoader chainedCL = (ClassLoading.ChainedClassLoader) classLoader; }
- 手动实例化(若构造方法可访问)
如果该类的构造方法不是私有,你可以自己传入一组类加载器来创建链式加载器:
ClassLoader[] delegateLoaders = new ClassLoader[]{ ClassLoader.getSystemClassLoader(), Thread.currentThread().getContextClassLoader() }; ClassLoading.ChainedClassLoader chainedCL = new ClassLoading.ChainedClassLoader(delegateLoaders);
- 从线程上下文类加载器获取
在部分框架运行时,线程上下文类加载器会被设置为ChainedClassLoader,可以直接获取并强转:
ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader(); if (ctxClassLoader instanceof ClassLoading.ChainedClassLoader) { ClassLoading.ChainedClassLoader chainedCL = (ClassLoading.ChainedClassLoader) ctxClassLoader; }
内容的提问来源于stack exchange,提问作者Slevin
相关产品推荐
相关产品推荐

