双亲委派模式和类加载器(自定义类加载器)

类加载器就是加载一个类的一块功能代码,实现了将类通过加载全过程。进而将类放到内存分配空间和初始化,再接下来就是愉快的使用类里面的属性和方法完成自己的业务开发需求啦。

类加载器有很多种,主要是为了根据Java定义的项目目录结构去加载不同的路径下的类,一般都是根据功能类型划分。

类加载器的分类:

(1) BootStrapClassLoad启动类加载器

主要负责加载lib文件夹目录下的jar包。(idea创建普通Java类不会自带,要手动生成)

(2)ExtendsionClassLoad扩展类加载器

主要加载ext目录下的扩展类。

(3)ApplicationClassLoad应用程序类加载器

加载class path 下面的类(idea中是target->classes目录下)
线程加载器:
线程加载器也有个名称线程上下文加载器,其实它是JVM在启动线程进行类加载的时候把应用程序类加载器赋予了当前线程而已。

(4)自定义类加载器

这是为了实现自己的需求自定义的类加载器;比如

1:你想加载一些其它目录路径下的类文件,
2:或者做一些不同版本的类兼容(同时运行,不自定义类加载器就只会运行一份,因为判断是否加载同一个类的标准就是三点:类名,包名,类加载器),
3:或者设计一些自主研发的框架结构等等都需要用到自定义类加载器。

类加载器的双亲委派模式:

设想一种情况,你写了一个String类,这很明显是不行的因为JVM已经有这个内存类了,但是因为存放目录不同,加载器不同,也成功加载了,那么调用的时候就乱套了。所以JVM里面设计了双亲委派模式防止这种情况。
当一个类通过自定义加载器或者应用程序加载器加载时,会先向上一级父类的加载器询问判断是否已经加载过这个类,比如:
自定义加载器------》应用程序加载器------》扩展类加载器------》启动类加载器
通过这一层层询问如果都没有,那么就确定这个类不会是Java自身定义的内部类。那么就再反方向推回,直到找到一个加载器可以加载(加载不了就是class not found error):
启动类加载器------》扩展类加载器------》应用程序加载器------》自定义加载器

自定义类加载器代码实现:

在这里插入图片描述

但是我做实验的时候,遇到一个很奇怪的没能解决的问题,就是明明已经读取成功字节码文件,在执行defineClass的时候就直接跳出debug,也没有catch到什么错误信息。

先上debug的图,可以很清晰看到字节码文件已经成功读取出来了,然后调用defineClass 转的时候就出问题:

在这里插入图片描述
在这里插入图片描述

后来问了大佬,传入的那个name不是.class文件的name。而是.class文件的全限定名。读取class文件和传入的name调用defineClass 方法是两回事,后来将代码改成这样就成功了,我之所以不把Hello.class放在SRC目录下是因为写全限定名加载时候,调用的是父类的加载器,我自定义的里面两个System.out输出都没打印出来,所以就换了个路径放,在这里也可以看出,不管文件放在哪里,自定义的类加载器都是可以加载到的:

在这里插入图片描述

谢谢这位大佬,鞠躬!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章