1. BootStrapClassLoader
2. ExtClassLoader
3. AppClassLoader (System ClassLoader)
类加载器的双亲委派机制,保证了核心类只能由BootStrapClassLoader加载,从而保证类加载的安全;
自定义类加载器,如果打破了双亲委派机制,则一个类可由自定义的类加载器进行加载,则此时一个类在JVM perm区中会存在多份,该场景常见于各类容器自定义的类加载器;此时使用cast进行类型转化会报错;
使用动态代理,JVM会为目标对象生成一个新的代理类;
JVM会为不同的类生成不同的代理类型,classloader会加载新的类;
如果多次为同一个类生成动态代理对象,JVM生成的代理类也只会加载一次;
4. ContextClassLoader
Thread.currentThread().getContextClassLoader()
Java中默认的类加载机制是使用双亲委托,假设有如下委托链:
ClassLoader A -> System Class Loader -> Extension Class Loader -> BootStrap Class Loader,
则委托链左边的ClassLoader可以方便地使用右边的ClassLoader所加载的类;
如果委托链右边的代码想找委托链左边的ClassLoader加载的东西在正常情况下无法实现,此时将委托链左边的ClassLoader设置为当前线程的Context ClassLoader,代码就可以不受双亲委托的限制而加载到该类了;
通过设置线程ContextClassLoader的方法,用户可以自定义类加载器,不同的类加载器加载同样的模块,实现模块的隔离
JDBC/JNDI/JAXP等都通过该机制实现,接口类由bootstrap classloader加载,具体实现通过设置context classloader进行加载;
开源的实现方案有阿里的jarslink:https://github.com/alibaba/jarslink
5. 资料
深入探讨Java类加载器 https://www.ibm.com/developerworks/cn/java/j-lo-classloader/
findClass ClassNotFoundException
defineClass NoClassDefineFoundError