在开发的过程中,我们一定遇到过java.lang.ClassNotFoundException或java.lang.NoClassDefError,为了解决这类问题,或者面对特殊的应用场景,比如需要支持类的动态加载或需要对编译后的字节码文件进行加密解密操作,那么需要我们来自定义类加载器(反编译操作),因此了解类加载器及其类加载机制也就成了每一个Java开发人员的必备技能之一。
1.类加载器的作用
(1)加载类(最基本的最核心的作用)
(2)加载类路径下的其他资源文件,如配置文件等。
2.类加载器的类型(4种)
加载器 | 负责加载 | 简要说明 |
---|---|---|
引导类型加载器(根加载器 Bootrap Classloder) | jre/rt.jar核心库 | 它本身不是Java代码实现的,也不是ClassLoader的子类,获取它的对象时往往返回null |
扩展类加载器(Extension ClassLoder) | jre/lib/ext扩展 | 它是ClassLoader的子类 |
应用程序类加载器(Application Classloader) | 项目的classPath路径下的类 | 它是ClassLoader的子类 |
自定义类加载器 | 程序需要加载“特定”目录下的类,我们可以自定义类加载器;当程序的字节码文件需要加密时,往往会提供一个自定义类加载器对其进行解码,比如常见的自定义类加载器:tomcat中 |
3.类加载器间的关系
⑴<应用程序类加载器>把【扩展类加载器】称为父加载器,<扩展类加载器>把【导类加载器】称为父类加载器,这里的“父”不是继承,而是在<应用程序类加载器>中有一个成员变量是扩展类加载器类型,名称是parent,同样的在<扩展类加载器>中有一个成员变量是引导类加载器类型,名称是parent。这种方式我们称为组合的关联关系,不是继承的关联关系。
⑵当调用getParent()方法时,既可以获取父加载器。
(3)这种“组合关联”的设计目的是什么?
Java的类加载器是双亲委托模式!
过程:
当下级的类加载器,例如 应用程序类加载器,接到加载某个类的任务时,
A.会先在内存中搜索这个类是否已经被加载过,如果加载过,就可以找到它的Class对象,那么直接返回这个Class对象就可以,不会重复加载。
B.如果在内存中并没有搜索到这个类的Class对象,说明这个类没有被加载过,它此时会把这个任务,提交给“父”加载器,
-
例如:应用程序类加载器,如果提交,就是给扩展类加载器;当扩展类加载器接到任务时,重复刚才的操作①②,这里,扩展类加载器,如果提交,就是给引导类加载器, 当引导类加载器接到任务时,重复刚才的操作①②,引导类加载器想要提交给父加载器时,发现没有父加载器了,然后在jre/rt.jar核心库先自己找一下,有没有这个类,如果找到了,就返回Class对象。
如果引导类加载器,在jre/rt.jar核心库中没有找到,再把任务往会传,给扩展类加载器, 此时因为是引导类加载器把这个任务重新给你的,那么你要在你负责的路径下,即jre/lib/ext扩展库,如果找到了,就返回Class对象。
如果扩展类加载器,在jre/lib/ext路径下没有找,再把任务继续往回传,给应用程序类加载器,此时因为是扩展类加载器把这个任务重新给你的,那么你要在你你负责的路径下,即项目的classpath路径下的类,如果找到了,就返回Class对象,如果应用程序类加载器,在项目的classpath路径下也没有找到,就报ClassNotFoundException。为什么要这么干? 目的:安全
- 例如:我们自己写了一个类:java.lang.String
如果此时没有“双亲委托模式”,应用程序类加载器先接到任务,加载“java.lang.String",它在项目中直接就找到这个类,内存中,就会存在一个String类型Class对象。
此时就会导致系统核心类库中的String类型失效了。
@Test public void test1(){ Class c = String.class; ClassLoader loader = c.getClassLoader(); System.out.println("String类的类加载器:" + loader); }
实际中有“双亲委托模式”,应用程序类加载器先接到任务,提交这个任务,一直到引导类加载器,引导类加载器会去jre/rt.jar核心库中找,可以找到,就返回,所以,应用程序类加载器就不会在自己负责的项目的classpath路径下去加载这个String类型。这样就可以保证核心类库的安全。
☝上述分享来源个人总结,如果分享对您有帮忙,希望您积极转载;如果您有不同的见解,希望您积极留言,让我们一起探讨,您的鼓励将是我前进道路上一份助力,非常感谢!我会不定时更新相关技术动态,同时我也会不断完善自己,提升技术,希望与君同成长同进步!
☞本人博客:https://coding0110lin.blog.csdn.net/ 欢迎转载,一起技术交流吧!