java ClassLoader 解读

classLoader类加载器

双亲委托,MyClassLoader -> AppClassLoader -> ExtClassLoader -> BootStrapClassLoader
首先MyClassLoader 在加载一个类的时候会先去自己已加载的类中去找,如果没有找见就去他的上级AppClassLoader 类中找,AppClassLoader 也没加载过的话就去ExtClassLoader 中找,以此类推,直到BootStrapClassLoader也发现没有加载,这个时候MyClassLoader 才会尝试自己加载,这是为了防止重复加载一个类的机制。

ClassLoader.getSystemClassLoader()这个方法会返回AppClassLoader
Thread.currentThread(),getContextClassLoader这个方法在IDEA以Application启动时会返回AppClassLoader,而以springboot启动时会返回springboot自己的classLoader,也就是LaunchedURLClassLoader,两者在IDEA中跑代码没有问题,但是在jar包启动的时候,AppClassLoader加载的url只有一个,而LaunchedURLClassLoader是以jar in jar的方式加载的,如下图

这个问题会导致一些自定义的URLClassLoader加载不到类,自定义URLClassLoader如果不指定父加载器的话默认是AppClassLoader,这个时候使用URLClassLoader会导致某些类加载不上,解决这个问题需要指定URLClassLoader的父加载器,

1
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url}, Thread.currentThread().getContextClassLoader())

使用Thread.currentThread().getContextClassLoader()即可
参考文章:http://blog.csdn.net/hengyunabc/article/details/77413669 (深入Spring Boot:ClassLoader的继承关系和影响)
http://blog.csdn.net/peter_k/article/details/1667685 (Thread.getContextClassLoader() 祥解, 详细解释了系统对于classLoader的选择)