jar的类加载器 Java.lang.ClassLoader

1、原理介绍

       ClassLoader使用的是双亲委托模型来搜索类的,每个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。

       

 

1、BootStrap ClassLoader:称为启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库,如:rt.jar、resources.jar、charsets.jar等,可通过如下程序获得该类加载器从哪些地方加载了相关的jar或class文件:

​

URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (int i = 0; i < urls.length; i++) { 
        System.out.println(urls[i].toExternalForm()); 
}

[点击并拖拽以移动]
​

//输出结果如下

bootStrap ClassLoader底层是用C++写的,不算是Java的类加载器,算是外部加载器。
 

 

2、Extension ClassLoader:称为扩展类加载器,负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目下的所有jar。

3、App ClassLoader:称为系统类加载器,负责加载应用程序classpath目录下的所有jar和class文件。

 注意: 除了Java默认提供的三个ClassLoader之外,用户还可以根据需要定义自已的ClassLoader,而这些自定义的ClassLoader都必须继承自java.lang.ClassLoader类,也包括Java提供的另外二个ClassLoader(Extension ClassLoader和App ClassLoader)在内,但是Bootstrap ClassLoader不继承自ClassLoader,因为它不是一个普通的Java类,底层由C++编写,已嵌入到了JVM内核当中,当JVM启动后,Bootstrap ClassLoader也随着启动,负责加载完核心类库后,并构造Extension ClassLoader和App ClassLoader类加载器。

ClassLoader,ExtClassLoader,AppClassLoader,BootstrapClassLoader四个加载器间的关系
 
ClassLoader loader = Main2.class.getClassLoader();    //获得加载ClassLoaderTest.class这个类的类加载器  
 		while(loader != null) {  
 		    System.out.println(loader);  
 		    loader = loader.getParent();    //获得父类加载器的引用  
 		}  
 		System.out.println(loader);  

结果:

sun.misc.Launcher$AppClassLoader@59727745
sun.misc.Launcher$ExtClassLoader@69f480e3
null  BootStrap ClassLoader不是一个Java的class,所以打印不出来

2、为什么要使用双亲委托这种模型呢?

       因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。考虑到安全因素,我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义的类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时就被引导类加载器(Bootstrcp ClassLoader)加载,所以用户自定义的ClassLoader永远也无法加载一个自己写的String,除非你改变JDK中ClassLoader搜索类的默认算法。

3 、但是JVM在搜索类的时候,又是如何判定两个class是相同的呢?

     JVM在判定两个class是否相同时,不仅要判断两个类名是否相同,而且要判断是否由同一个类加载器实例加载的。只有两者同时满足的情况下,JVM才认为这两个class是相同的。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]和\[2\]中提到的异常"java.lang.NoClassDefFoundError: org/dom4j/DocumentException"是由于缺少dom4j包导致的。要解决这个问题,你可以按照以下步骤进行操作: 1. 在你的jar包的目录下创建一个lib文件夹,并将dom4j包放入其中。 2. 使用解压软件打开你的jar包,找到META-INF文件夹,并进入其中。 3. 在META-INF文件夹中找到名为MANIFEST.MF的文件。这个文件不能在压缩包内直接修改,所以需要将其中的内容复制出来。 4. 在复制出来的MANIFEST.MF文件中,找到第二行,原先可能没有"Class-Path: lib/dom4j-2.1.1.jar"这一行。在这一行中,lib表示刚刚创建的lib文件夹,dom4j-2.1.1.jar是dom4j包的名称。 5. 修改完后,将修改后的MANIFEST.MF文件保存,并将其直接拖到压缩包内的META-INF文件夹中,替换原来的文件。 6. 重新运行程序,你会发现问题已经解决了。 需要注意的是,在修改MANIFEST.MF文件时,确保文件的第三行结束后按下回车键,以确保有四行内容,第四行不需要写任何内容。\[2\] 引用\[3\]中的异常信息"at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1189) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) ... 44 more"可能是与Web应用程序的类加载器相关的错误信息,但与解决缺少dom4j包的问题无关。 综上所述,要解决"java.lang.NoClassDefFoundError: org/dom4j/DocumentHelper"的问题,你需要按照引用\[2\]中提供的步骤添加dom4j包,并修改MANIFEST.MF文件。这样就能够成功加载org.dom4j.DocumentHelper类,解决异常问题。 #### 引用[.reference_title] - *1* *3* [java.lang.NoClassDefFoundError: org/dom4j/DocumentException](https://blog.csdn.net/zyuc_wangxw/article/details/6987623)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [初学者遇到java.lang.NoClassDefFoundError: org/dom4j/DocumentException解决方法](https://blog.csdn.net/abc630727719/article/details/104257070)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值