详细拆解ClassLoader的相关知识点

	面试官:说一下classLoader是用来做什么的?

有人就想了,不就是一个类加载器吗,把类加载的机制和流程说一下就可以了

你可以先考虑下你的答案是什么,如果可以的话,最好自己组织一下语言,然后写出来或者自己录音录下来,看看是否对自己的答案感到满意

好了,我写的也不一定是标准答案,你不一定非要和我的一模一样,但是如果你不知道怎么回答的话,可以按照我提供的这个顺序去回答,最起码不会拉低你的水平

敲黑板
思路:
ta是什么?
ta有什么用?
ta为什么要这么用?
和ta相关的东西都有哪些?

答:ClassLoader是一个加载类,也就是类加载器

作用主要有三个:
第一:是将Class加载到JVM里面,当运行Java程序的时候,首先会被编译成class文件,而class文件的运行是在jvm里面的,而负责加载class文件的部分就是ClassLoader

第二:就是审查每个类由谁加载(父类优先的等级加载机制)

第三:就是将 Class 字节码重新解析成 JVM 统一要求的对象格式

以上三条是先总结classLoader,一般情况下,初级程序员(15k以下)基本上到这里估计也就回答完了,接下来等待面试官的询问

但,如果你是中高级程序员,说完之后立马补充以下部分:

而一个类被加载到虚拟机内存中,到卸载出内存会经历以下过程 :
1⃣️加载 -> 2⃣️连接(验证,准备,解析)-> 3⃣️初始化 -> 4⃣️卸载
(简单记住流程就是1加2连3初始)

其中什么时候开始加载,并没有强行规定,不同虚拟机会有不同的规则,但是加载的时候虚拟机主要干三件事:

一 加载:
1.通过类的全限定名来获取到该类的二进制字节流(获取二进制流除了读取.class文件之外,还可以从jar包,war包里面读,还可以通过动态代理生成代理类的二进制字节流)

2.将二进制字节流所代表的静态结构转化为方法区的运行时数据结构

3.在内存中创建一个代表该类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口
说完之后,再来一句装逼的话,另外源码里面有交代,array类本身是不通过类加载器创建的,是由 JVM 直接创建的,再由类加载器创建数组中的元素类(讲虚拟机的书里都有交代)

二 验证:
验证的过程主要是***确保Class 文件的字节流,里面包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全***

准备:为静态成员变量分配内存并赋初始值,这些变量所使用的内存都在方法区中进行分配

解析:虚拟机将常量池内的符号引用替换成直接引用,会把该类所引用的其他类全部加载进来( 引用方式:继承、实现接口、域变量、方法定义、方法中定义的本地变量)

而符号引用就是一个 java 文件会编译成一个class文件。在编译时,java 类并不知道所引用的类的实际地址,因此只能使用符号引用来代替

说到符号引用,就会对比直接引用,直接引用就是直接指向目标的指针(指向方法区,Class 对象)、指向相对偏移量(指向堆区,Class 实例对象)或指向能间接定位到目标的句柄。

3⃣️初始化:执行类构造器() 方法的过程。该方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的,一个类对应一个,并且是无参,换句话说如果一个类没有静态语句块,也没有对类变量的赋值操作的话,编译器可以不为这个类生成 () 方法,

另外需要注意的是:方法的区别,Class 类实例构造器,对非静态变量解析初始化,也就是new 一个对象,然后调用 constructor 方法时才会执行init方法

说到这里,基本上面试官可以断定你对类加载器和类加载机制一定有非常深入的研究,印象分就立马高了很多,接下里再问到别的,不会的你就可以说没有研究那么深入,会的就正常作答就好

其实这里主要是要突出一个效果,这个效果是给面试官展现的,就是你要让面试官认为你是一个靠谱且钻研的人,达到这个效果就足够了

那么怎么展现这样的效果呢,就是一句话,不求面面俱到,但必须要有一个方面足够深入,足够深入,深入到让别人听都没有听过的最好

补充:
对于初始化,虚拟机规范是有明确的指明,不是一个类进来就会被初始化
我总结了有5种情况就会对类进行初始化:

1.创建类的实例
2.对一个类进行反射调用的时候
3.当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化
4.当虚拟机启动时,用户需要指定一个要执行的主类(包含main 方法的那个类),虚拟机会先初始化这个主类
5.当使用jdk1.7动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getstatic,REF_putstatic,REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先出触发其初始化。

	 ---->类的实例化是指创建一个类的实例(对象)的过程;
	---->类的初始化是指为类中各个类成员(被static修饰的成员变量)赋初始值的过程,是类生命周期中的一个阶段

如果你能看到这里,面试就要资深研发起步了,下面的部分,两年以上工作经验的人请务必会,因为三年是一个门槛

继续与面试官聊,对了,我还看到ClassLoader里面有个findClass方法,这个方法的作用是通过覆盖ClassLoader父类的findClass方法来实现类的加载规则,从而取得要加载类的字节码,然后再调用defineClass方法来生成类的Class对象,defineClass方法用来将字节流解析成jvm能够识别的class对象,实际上如果直接调用这个方法生成类的 Class 对象,这个类的 Class 对象还没有进行resolve ,这个 resolve 将会在这个对象真正实例化时才进行,当然如果你想在类被加载到JVM中时就被链接,那么可以接着调用另一个 resolveClass 方法

面试官听你讲到这里,基本上对你已经定级了,随后可能会问几个简单的问题,但是你这时候不应该停止,上面的所有回答都是回答了classLoader这个具体的东西,都是极度微观的,如果面试官没有打断你的意思,那么话锋一转

可以这样说:“以上就是我对classLoader的一些微观简单研究,宏观来看的话,还有下面这些东西”

对于Java来说,默认提供了三个ClassLoader,分别是
Bootstrap ClassLoader
ExtClassLoader
AppClassLoader

其中Bootstrap ClassLoader叫做启动类加载器,是由jvm提供的,是Java类加载层次中最顶层的类加载器,负责加载jdk中核心类库,如rt.jar,resources.jar

ExtClassLoader叫做扩展类加载器,是负责加载Java的扩展类库的,默认加载JAVA_HOME/jre/lib/ext/目下的所有jar

AppClassLoader叫做系统类加载器,负责加载应用程序classpath目录下的所有jar和class文件

除了bootstrap classLoader没有父类加载器,其他所有的类加载器都有一个父类加载器

appClassLoader --> ExtClassLoader --> bootrap ClassLoader

而一般情况下我们开发人员编写的类加载器的父类加载器是系统类加载器
这句话一定要说

另外说到类加载器,也会涉及到双亲委派模型,这都是互相连接的,下面我在简单说下双亲委派模型为什么是从上到下的的,也是为什么开发人员编写的类加载器的父类加载器是系统类加载器

如果能看懂源码的流程的,就把下面源码的逻辑流程说下,看不懂的也没有关系,直接说流程就好

部分源码是在rt.jar 下面的sun.misc包下

ClassLoader加载类的原理是通过***双亲委派模型***来搜索加载类的,也就是说当一个ClassLoader实例需要加载某个类时,在它自己搜索加载这个类之前,先让其父类加载器去加载,如果父类没有找到,那么就让父类的父类的去加载,这个过程是由上到下的,也就是说要先bootstrap ClassLoader先去加载,如果没有的话,在由自己亲自加载,如果还没有的话,就会报错ClassNotFoundException,否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象

另外在Launcher这个类里面可以看到,Launcher初始化了ExtClassLoader和AppClassLoader,并将AppClassLoader设置为线程上下文类加载器。
在这里插入图片描述
另外还可以看到ExtClassLoader和appClassLoader都继承UrlClassLoader,而UrlClassLoader里面又有一个super(parent),在前面ClassLoader 源码中,我们知道有个parent 字段,这里就是在初始化这个字段。这里ExtClassLoader 作为了AppClassLoader 的parent

***双亲委派模型加载的好处***就在于,可以避免重复加载,另外一方面这样也很安全,假如不用双亲委派的方式,使用自己的类加载器优先去加载,那么自定义的类型就可以替代Java核心api里面的类型

以上就是我对于classLoader的理解以及相关的一些研究

好,回答到这里,总体上类加载器的相关东西都已经被你抖落出来了,知道就是知道,不知道就是不知道,看过源码的就把源码说下,没看过也不要紧,总之就是你要以classLoader为圆心,以其他涉及到classLoader的知识点为半径,画一个完整的圆,就算是你哪点漏掉了,也不会妨碍你整体发挥

这就是面试,有的人技术很强,可是你让他说一个classLoader他也说不来这么多东西,而有的人技术一般,但是就是可以答出这样貌似完整的答案,你说你作为面试官,你会选择哪个

所以就像我一直强调的,做事要大处着眼,小处着手,面试更是如此,微观入局,宏观收局,主控权一直都在你这边,有了主控权你才可以把你的技术才华都抖落出来

好了,关于classLoader就到这吧,希望对你有帮助!

	文笔有限,多多包涵
	如有雷同,算我抄你
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值