ClassLoader作用
?classloader这个写业务代码的童鞋们,应该很少用到,但是写框架的应该很熟悉。这个类负责Java底层的类的加载和查找,简单滴说Java 的所有类都是由它负责将class文件加载到JVM
? ? 这篇文章主要是讲解,ClassLoader是如何查找和加载类的
常用的ClassLoader
??①:BootStrapClassloader? 负责加载jre下面的核心类
? ?②:ExtClassLoader? ? ? 负责加载jre/ext下面的类
? ?③:AppClassloader? ? ? 负责加载classpath下面的类或者jar,这个classpath很广,包括(我们平常能接触到也就是这个AppClassload)
? ? ? ? ? ? ? ? ? ? ?①:jre/lib下面的部分包
? ? ? ? ? ? ? ? ? ? ?②:web项目的classpath路径下的所有的类和资源
? ? ? ? ? ? ? ? ? ? ?③:web项目依赖的第三方jar包
? ?④:自定义classloader
? ?如果有兴趣的话,你们可以分别打印出每个classloader管理的资源,代码如下
ClassLoader如何发现资源? ?
这段是基础介绍,如果大家知道可以跳过
一,各个Classloader的关系直接上图(双亲委托机制)
? ? ? ? ?? ?查找一个.class文件时,从上图可以看到,
? ? ? ? ? ? ①:查找资源的时候appClassloader会将查找任务先委托给自己的上级ExtClassloader
? ? ? ? ? ? ②:ExtClassloader会将查找任务先委托给上级BootStrapClassloader
? ? ? ? ? ? ③:只有在上级查找不到情况下,自己再负责查找资源并加载
? ? ? ? ? ? 经典加载代码?Thread.currentThread().getContextClassLoader().loadClass("");
这段是基础介绍,如果大家知道可以跳过
问题
? ? 问题1:每个classloader 管理的资源存储在什么地方
? ? 问题2:项目依赖的jar包本身还要依赖第三jar包,此时classloader又该如何处理
示例
main方法执行后,JVM是如何加载main方法所在的类
? ? ? 首先大家要知道JVM是不会傻傻的在启动时候,直接将程序中所有的类和资源都加载进内存,JVM秉承的设计原则就是,用时再加载,不用的时候,你就歇着吧(JVM作为BOSS 很抠的哈),那么JVM是怎么加载main方法所在的类尼
? ? ? ①:程序启动的时候,JVM负责先装载所有的classLoader(这一部分,大家不用深究,具体JVM怎么下指令的,这个东西是底层做的,我们也看不懂),我们只需要知道JVM帮忙实例化了sun.misc.Launcher这个类,在这个构造函数中
,装载所有的Classloader(主意:BootstrapClassloader不归它管,你可以理解BootstrapClassloader为JVM直辖(就像直辖市一样))
②:加载main方法所在的类如:A,调用的部分流程如下:最终调用Classloader.loadClass这个方法加载A类,这个类(典型的双亲委托模式实例)
? ? ? ??? ?③:带着问题分析一下ClassLoader.loadClass 这个类
从上文得知findClass()这个方法是具体负责加载资源,但是你点击进去会发现这是一个为空实现,看看这个类的继承关系,AppClassLoader父类为URLClassLoader,我们到URLclassLoader上看看
其实到这里,我们已经可以看到,其实是类查找和加载UCP?这个对象操作,UCP(是URLClasspath这个类的实例)
??ps:这里的涉及到缓存的代码,暂时不要看(如:getLookUpCache()),基本上都无法名中(反正我debug的时候,没啥用)
重点来啦,要看懂上述这段代码,就不的不提一下上面讲的那个类URLClassPath 和URLClassPath.loader这个内部类
path:初始化类加载器的时候,设置类记载器管理的默认资源列表(比如appclassLoader 这个类加载器,这个path中主要存储的是项目依赖的jar包路径(不包括此ar包依赖的第三方jar),jre/lib下的部分jar)
urls:其实初始化完成以后应该和path一样,区别在于urls还会解决这个问题(问题2:项目依赖的jar包本身还要依赖第三jar包,此时classloader又该如何处理),
也就是说,urls初始化完成以后,还会去加载jar包依赖的第三方jar包,怎么加载的(下面分析)(这是一个栈的数据结构,先进后出)
loaders:这个属性有点强啦,是资源抽象(URLClassPath.loader)的列表,提供一个非常关键的方法? Resource getResource(String var1, boolean var2) ,负责匹配资源(或者说在这个资源中能不能找到这个要加载的类)
? ? ? ? ? ? ? ?URLClassPath.loader? 有2个具体的实现类,每个都重写了getResource这个方法
lamp 这个其实作用不是很大,做一个缓存的作用,如果URLClassPath.loader实例化过啦,直接从缓存中取出,不用重新实例化啦
那么我们现在再来分析一下,getLoader这个方法
给大家画了一张简单时序图