本文使用 Zhihu On VSCode 创作并发布
之前在看java类加载机制的时候,就在想,JVM是如何在Jar包中找到某个具体的Class文件,如果是把Jar包解压到一个指定的文件中,那我还能理解,他是先解压然后在去解压后的文件中查找有没有具体的文件,但事实上,jvm在运行java程序时候,并没有将jar包解压。所以就比较好奇jvm是如何获取到具体的class文件。本篇文章主要对其进行探究。
这里就不在叙述类加载机制,直接定位到具体加载Class文件资源的函数,代码如下:
protected
在上面代码中,主要获取的Class文件资源的代码就是下面俩句
String
其中ucp指的就是URLClassPath这个类,也就是说,jvm是通过这个类来定位具体的Class资源。
获取Class文件资源流程
下面是本文debug时创建的一个函数,用于跟踪URLClassPath是如何加载class资源文件的。
URL
这里有一点需要注意的是,在定位具体的class文件中,要把类名中的点转换成"/"。
首先补充一点知识,方便后面理解,URLClassPath是通过根据文件类型创建不通的Loader来加载具体的资源。这些Loader是URLClassPath的内部类,具体继承关系如下图。
![b995346924a95333b5e27fd144dc865f.png](https://img-blog.csdnimg.cn/img_convert/b995346924a95333b5e27fd144dc865f.png)
URLClassPath#getResource
public
这个方法,主要的作用就是循环所有的Loader,查找是否有对应的资源文件
URLClassPath#getNextLoader
private
首先需要注意的是,这个方法是线程安全的。方法主要有俩个作用
- 如果文件对应的Loader已经创建,则返回缓存的Loader
- 如果没有缓存,进行创建,即this.getLoader(var2)这句
URLClassPath#getLoader(int var1)
下面先补充函数中用到的属性
// 存储创建的Loader
private
上面函数主要处理流程:
- 如果传入的索引小于等于loaders缓存的长度,则直接返回对应索引的Loader,否则进入第二步
- 从urls栈中取出栈顶URL并创建对应的Loader,并对Loader进行缓存
URLClassPath#getLoader(URL var1)
private
这里主要根据文件类型创建Loader。到此为止,已经将怎样创建并获取Loader流程讲完。下面介绍如何通过Loader获取具体的Resource
URLClassPath.JarLoader#getResource(String, boolean)
Resource
上面最后一步的this.getResource(var1, var2, var4);我是真的看的头疼,不过具体的逻辑上面已经展示出来,哪位大神已经理解的话,可以把自己的理解放在回复里。 URLClassPath.FileLoader#getResource和URLClassPath.Loader#getResource大体上与此相似。