JAVA类加载的委托模型

简介:

关于JAVA的类加载器,网上有很多这方面资料,这里只做测试,不多累述。JVM有三个内置加载器:           bootstrapClassLoader(由C语言编写,固化在jvm上)、ExtClassLoader、AppClassLoader。三个加载器从上到下呈父子关系,形成了“类加载委托模型”:即儿子的事情,父亲能做的,他一定会代劳(以免累到儿子),父亲的事情,一定会自已做,即使自已无法完成,也不会劳及儿子。三个类的加载路径分别为(更多细节参考google):

BootstrapClassLoader:    sun.boot.class.path 
ExtClassLoader:     java.ext.dirs                                                                                   AppClassLoader:     java.class.path

 

 首先定义两个类:

 
  1. package loader;  
  2.  
  3. public class ClassA {  
  4.    public static void main(String args[]){  
  5.        System.out.println("ClassA: " + ClassA.class.getClassLoader());  
  6.  ClassB a = new ClassB();  
  7.        System.out.println("ClassB: " + ClassA.class.getClassLoader());  
  8.    }  
  9. }  
  10. //
  11. package loader;  
  12.  
  13. public class ClassB {  

拷贝三份到:C:\Java\jre6\classes(bootstrapClassLoader的搜索目录之一),C:\Java\jre6\lib\ext\classes(extClassLoader的搜索目录之一),F:\javawork\study\bin目录下,其中C:\Java\jre6为我JRE目录。一定不要搞错,因为你的机器可能会有很多JRE。

CMD到F:\javawork\study\bin目录

1. F:\javawork\study\bin>java loader.ClassA
ClassA: null
ClassB: null

两个都为空,这是因为当AppClassLoader(默认的系统类加载器)来加载CLASSA,首先委托其父ExtClassLoader去加载,然后AppClassLoader委托bootstrapClassLoader去加载,bootstrapClassLoader没有父加载器,只能自已完成,在自已加载目录C:\Java\jre6\classes下找到了CLASSA,加载成功。然后CLASSA的加载器bootstrapClassLoader加载CLASSB,同样在C:\Java\jre6\classes找到CLASSB,所以两个类的加载器都是bootstrapClassLoader,因为bootstrapClassLoader实现于C++,所以返回NULL。

2. 删除C:\Java\jre6\classes目录下的CLASSB

F:\javawork\study\bin>java loader.ClassA
ClassA: null
Exception in thread "main" java.lang.NoClassDefFoundError: loader/ClassB
        at loader.ClassA.main(ClassA.java:6)

这是因为同(1)一样,最后由bootstrapClassLoader成功加载CLASSA,然后由CLASSA(这里叫CLASSB的CALLER)的加载器bootstrapClassLoader需要去加载CLASSB,但bootstrapClassLoader尽其力也没能找到(因为被我删了),这位慈爱的父亲到最后一刻都没有交给儿子ExtClassLoader去做,最后上报:我无能为力。

3.把(2)中删除的CLASSB还原,同时删创除该目录下的CLASSA

F:\javawork\study\bin>java loader.ClassA
ClassA: sun.misc.Launcher$ExtClassLoader@126b249
ClassB: null

两个都输出ExtClassLoader,顺着(1)的思路,AppClassLoader委托ExtClassLoader,ExtClassLoader委托bootstrapClassLoader,bootstrapClassLoader找不到CLASSA,只能放手让儿子去做(比如找女朋友这事,小伙子本来想老爸战友的女儿不错,可父亲去提亲,人家不应,“不行,儿子,你自个追其他的吧!”)。ExtClassLoader绝地逢生,在自已的区域内找到了CLASSA。然后CLASSA的加载器ExtClassLoader去加CLASSB, 同样道理这事交给老爸bootstrapClassLoader去做,bootstrapClassLoader责无旁贷,顺利完成,所以ClassB: null。

4.把(3)中剩下的CLASSB也删除。

 F:\javawork\study\bin>java loader.ClassA
ClassA: sun.misc.Launcher$ExtClassLoader@ad3ba4
ClassB: sun.misc.Launcher$ExtClassLoader@ad3ba4

同(1)一样,ExtClassLoader绝地逢生,在自已的区域内找到了CLASSA,然后CLASSA的加载器ExtClassLoader去加CLASSB,不幸的事,这次老爸bootstrapClassLoader却无能为力(被我CUT了)。最后ExtClassLoader自已搞定。

5.继序(4)删除C:\Java\jre6\lib\ext\classes目录下的CLASSB

F:\javawork\study\bin>java loader.ClassA
ClassA: sun.misc.Launcher$ExtClassLoader@126b249
Exception in thread "main" java.lang.NoClassDefFoundError: loader/ClassB
        at loader.ClassA.main(ClassA.java:6)

按上面的思路,你一定知道为什么。

6.还原(5)中删除的CLASSB,同时删除CLASSA.

F:\javawork\study\bin>java loader.ClassA
ClassA: sun.misc.Launcher$AppClassLoader@ad3ba4
ClassB: sun.misc.Launcher$ExtClassLoader@126b249

AppClassLoader(默认的系统类加载器)来加载CLASSA,首先委托其父ExtClassLoader去加载,然后AppClassLoader委托bootstrapClassLoader去加载.可两们前辈都无能为力,最后还是落到了AppClassLoader身上,少年英雄很快实现自已的梦想,成功加载CLASSA,然后其CLASSA的加载器(还是AppClassLoader)再去加载CLASSB,喜出望外的是,老爸ExtClassLoader代其完成,大功告成。

7.继序(6)删除C:\Java\jre6\lib\ext\classes目录下的CLASSB 

F:\javawork\study\bin>java loader.ClassA
ClassA: sun.misc.Launcher$AppClassLoader@ad3ba4
ClassB: sun.misc.Launcher$AppClassLoader@ad3ba4

同样道理,委托,委托。但这次AppClassLoader在我的破坏下(我删,删),只能自力更生。完成加载。

有一点问题,在测试过程中我的本机并没有CLASSPATH变量:

F:\javawork\study\bin>set classpath
环境变量 classpath 没有定义

但System.out.println(System.getProperty("java.class.path")) 输出:. 即当前目录作为了classpath.



本文转自 anranran 51CTO博客,原文链接:http://blog.51cto.com/guojuanjun/464708

目录
打赏
0
0
0
0
347
分享
相关文章
Java 大视界 -- Java 大数据机器学习模型在遥感图像土地利用分类中的优化与应用(199)
本文探讨了Java大数据与机器学习模型在遥感图像土地利用分类中的优化与应用。面对传统方法效率低、精度差的问题,结合Hadoop、Spark与深度学习框架,实现了高效、精准的分类。通过实际案例展示了Java在数据处理、模型融合与参数调优中的强大能力,推动遥感图像分类迈向新高度。
Java 大视界 -- Java 大数据机器学习模型在游戏用户行为分析与游戏平衡优化中的应用(190)
本文探讨了Java大数据与机器学习模型在游戏用户行为分析及游戏平衡优化中的应用。通过数据采集、预处理与聚类分析,开发者可深入洞察玩家行为特征,构建个性化运营策略。同时,利用回归模型优化游戏数值与付费机制,提升游戏公平性与用户体验。
Java 大视界 -- Java 大数据机器学习模型在舆情分析中的情感倾向判断与话题追踪(185)
本篇文章深入探讨了Java大数据与机器学习在舆情分析中的应用,重点介绍了情感倾向判断与话题追踪的技术实现。通过实际案例,展示了如何利用Java生态工具如Hadoop、Hive、Weka和Deeplearning4j进行舆情数据处理、情感分类与趋势预测,揭示了其在企业品牌管理与政府决策中的重要价值。文章还展望了多模态融合、实时性提升及个性化服务等未来发展方向。
Java 对象模型现代化实践 基于 Spring Boot 与 MyBatis Plus 的实现方案深度解析
本文介绍了基于Spring Boot与MyBatis-Plus的Java对象模型现代化实践方案。采用Spring Boot 3.1.2作为基础框架,结合MyBatis-Plus 3.5.3.1进行数据访问层实现,使用Lombok简化PO对象,MapStruct处理对象转换。文章详细讲解了数据库设计、PO对象实现、DAO层构建、业务逻辑封装以及DTO/VO转换等核心环节,提供了一个完整的现代化Java对象模型实现案例。通过分层设计和对象转换,实现了业务逻辑与数据访问的解耦,提高了代码的可维护性和扩展性。
108 1
Java 大视界 -- Java 大数据机器学习模型在金融衍生品定价中的创新方法与实践(166)
本文围绕 Java 大数据机器学习模型在金融衍生品定价中的应用展开,分析定价现状与挑战,阐述技术原理与应用,结合真实案例与代码给出实操方案,助力提升金融衍生品定价的准确性与效率。
Java 大视界 -- Java 大数据机器学习模型在金融衍生品定价中的创新方法与实践(166)
【Java进阶】详解JavaScript的BOM(浏览器对象模型)
总的来说,BOM提供了一种方式来与浏览器进行交互。通过BOM,你可以操作窗口、获取URL、操作历史、访问HTML文档、获取浏览器信息和屏幕信息等。虽然BOM并没有正式的标准,但大多数现代浏览器都实现了相似的功能,因此,你可以放心地在你的JavaScript代码中使用BOM。
129 23
|
10月前
|
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
124 1
java的委托机制 .....代理模式
下面的SpaceShip类 我们用到了 SpaceShipControl类的方法,我们如果通过继承 或者 成员的方式直接调用  SpaceShipControl无疑暴露了我们的内部行为  .. 所以这时候我们就需要一个内部的代理来 实现方法的调用 。
690 0
|
1月前
|
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
84 0

热门文章

最新文章

AI助理
登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问

你好,我是AI助理

可以解答问题、推荐解决方案等