Java类载入器
1. 系统载入器简单介绍
Java虚拟机中能够安装多个类载入器,系统默认三个主要类载入器(BootStrap、ExtClassLoader、AppClassLoader)。每一个类载入器负责载入特定位置的类。
类载入器本身也是Java类(BootStrap除外)。由于它本身也要被类载入器载入,这样显然一定有第一个类载入器不是Java类。没错,正是BootStrap类载入器。它是由C++语言编写的。嵌在了Java虚拟机内核中的类载入器。当启动Java虚拟机时,它就被载入了。
2. 类载入器的结构与管辖范围
Java虚拟机中的全部类载入器採用具有父子关系的树形结构进行组织。在实例化一个类载入器对象时都须要为其指定一个父级类载入器对象,或者默认採用系统类载入器为其父级类载入。类载入器的树形结构与管辖范围例如以下图:
3. 类载入器的托付机制
当Java虚拟机载入某一个类时,究竟派出哪个类去载入呢?载入时遵循例如以下几个原则:
原则1:首先派出当前线程的类载入器载入类
原则2:每一个类载入器载入类时又先托付给其上级载入器。当全部的祖宗载入器没有载入到类,才回到发起者载入器。假设还没有载入到类,则将会抛出ClassNotFoundException。不会再去找发起者载入器的儿子,由于没有getChild方法,即使有,那么多个儿子(父类仅仅有一个),找哪一个呢?
原则3:假设类A引用了类B,那么Java虚拟机将使用载入类A的载入器来载入类B。
原则4:还能够直接指定某个载入器来载入类,如:ClassLoader.loadClass()。
注意,每一个ClassLoader本身分别仅仅能载入特定位置和文件夹中的类。但它们能够托付其他类载入器去载入类,这就是类载入器的托付模式。类载入器一级一级托付到BootStrap类载入器,当BootStrap无法载入当前所要载入的类时,然后才一级一级退回到子孙载入器去载入该类。
当退回到最初的类载入器时,假设它自己也不能完毕类的载入,那么会抛出ClassNotFound异常。
4. 举例1
首先我们定义一个空类TestClassLoader,代码例如以下:
package com.tgb.ClazzLoaders;
public class TestClassLoader {
}
然后我们再定义一个測试类TestMain来输出TestClassLoader类的类载入器名称:
package com.tgb.ClazzLoaders;
public class TestMain {
public static void main(String[] args) throws Exception {
// 输出类TestClassLoader的当类载入器的名称
System.out.println(TestClassLoader.class.getClassLoader().getClass().getName());
}
}
输出结果例如以下,为sun.misc.Launcher$AppClassLoader:
然后我们将类TestClassLoader打成一个jar包放到当前使用的jre\lib\ext文件夹下。例如以下图:
再次执行測试类TestMain,我们能够惊奇的发现输出结果变为了sun.misc.Launcher$ExtClassLoader。
这正验证了我们上面的类载入器托付机制。当载入TestClassLoader类时。当前的类载入器会向父级载入器一级一级托付,然后退回到ExtClassLoader时,它在自己的管辖范围内jre\lib\ext\*.jar。能够找到TestClassLoader这个类。
然后就将它载入了。
也是就说我们执行时用到的TestClassLoader类已经不是Eclipse中我们看到的这个类了,而是jre\lib\ext文件夹下我们打的TestClassLoader.jar中的类。
注意:一定要放到我们当前使用的jre文件夹下,否则不起作用,例如以下步骤可确认,右击项目---- >属性--->Run/Debug Settings找到自己的configuration,然后Edit查看JRE,例如以下图:
我将jre\lib\ext文件夹下我们打的TestClassLoader.jar删除掉。然后改造測试类,循环输出类TestClassLoader的当类载入器的名称,以及全部父类载入器的名称。代码例如以下:
package com.tgb.ClazzLoaders;
public class TestMain {
public static void main(String[] args) throws Exception {
// 输出类TestClassLoader的当类载入器的名称,以及全部父类载入器的名称
ClassLoader loader = TestClassLoader.class.getClassLoader();
while (loader != null) {
System.out.println(loader.getClass().getName());
loader = loader.getParent();
}
}
}
结果例如以下:
5. 举例2
编写一个能打印出自己的类载入器和当前类载入器的父子结构关系链的MyServlet,正常公布后。看到打印结果例如以下:
把MyServlet文件打Jar包,放到ext文件夹中,重新启动tomcat.发现找不到Httpservlet的错误。
把servlet.jar也放到ext文件夹中.问题攻克了。打印的结果是ExtclassLoader。
由此说明,父级类载入器载入的类无法引用仅仅能被子级类载入器载入的类。例如以下图:
6. 总结
系统默认三个主要类载入器(BootStrap、ExtClassLoader、AppClassLoader),每一个类载入器负责载入特定位置的类。
Java虚拟机中的全部类载入器採用具有父子关系的树形结构进行组织。类载入器有一定的托付机制。
此外。我们能够自己定义自己的类载入器(继承ClassLoader)。然后指定类载入器的管辖范围(载入文件夹),然后我们就能够在类载入的时候对类进行一些特殊处理(比如加密)。
Java类载入器的更多相关文章
- Java类载入器原理分析
一:Java虚拟机中能够安装多个类载入器,系统默认是三个基本的类载入器: Bootstrap ExtClassLoader AppClassLoader 类载入器也是Java类.由于其它Java类 ...
- Java类载入器 ClassLoader的解析
//參考 : http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类载入器基本概念 类载入器是 Java 语言的一个创新,也是 Ja ...
- Java类载入器(一)——类载入器层次与模型
类载入器 虚拟机设计团队把类载入阶段中的"通过一个类的全限定名来获取描写叙述此类的二进制字节流"这个动作放到Java虚拟机外部去实现.以便让应用程序自己决定怎样去获取所须要的类 ...
- Java类载入器(二)——自己定义类载入器
用户定制自己的ClassLoader能够实现以下的一些应用: 自己定义路径下查找自己定义的class类文件,或许我们须要的class文件并不总是在已经设置好的Classpath以下,那么我们必须想 ...
- java类载入器——ClassLoader
Java的设计初衷是主要面向嵌入式领域,对于自己定义的一些类,考虑使用依需求载入原则.即在程序使用到时才载入类,节省内存消耗,这时就可以通过类载入器来动态载入. 假设你平时仅仅是做web开发,那应该非 ...
- 黑马程序猿——Java中的类载入器
------- android培训.java培训.期待与您交流! -------- 类载入器 Java虚拟机中能够安装多个类载入器,系统默认三个主要类载入器,每一个类负责载入特定位置的类: BootS ...
- 深入研究Java类载入机制
深入研究Java类载入机制 类载入是Java程序运行的第一步,研究类的载入有助于了解JVM运行过程,并指导开发人员採取更有效的措施配合程序运行. 研究类载入机制的第二个目的是让程序能动态的控制类载 ...
- Jboss7类载入器
1. 类载入器理论知识介绍 类载入器基于Jboss Module,代替了层次类载入环境,避免了当类存在多个版本号时,导致类载入错误. 类载入是基于模块的.必须显示的定义模块依赖.部署也是模块化的,假设 ...
- Tomcat类载入器机制(Tomcat源代码解析六)
要说Tomcat的Classloader机制,我们还得从Bootstrap開始.在BootStrap初始化的时候.调用了org.apache.catalina.startup.Bootstrap#in ...
随机推荐
- 多校第二场 1004 hdu 5303 Delicious Apples(背包+贪心)
题目链接: 点击打开链接 题目大意: 在一个周长为L的环上.给出n棵苹果树.苹果树的位置是xi,苹果树是ai,苹果商店在0位置,人的篮子最大容量为k,问最少做多远的距离可以把苹果都运到店里 题目分析: ...
- 建议53:用状态模式美化代码,关于python-state工具包的理解
在<编写高质量代码:改善python程序的91个建议>的建议53:用状态模式美化代码小节中,介绍了状态模式例如以下:就是当一个对象的内在状态改变时,同意改变其行为,但这个对象看起来 ...
- Linux Kernel(Android) 加密算法总结(一)(cipher、compress、digest)
1. Linux内核支持哪些加密算法 ? 内核支持的加密算法非常多,包含: 对称加密算法.如AES,3DES. 对称password体制的发展趋势将以分组password为重点. 分组password ...
- do while 循环和while循环的差别
do while 循环和while循环的差别 1.do while循环是先运行循环体,然后推断循环条件,假设为真,则运行下一步循环,否则终止循环. while循环是先推断循环条件,假设条件为真则 ...
- XML系统学习
参考:W3School XML基本概念 1.XML是eXtensible Markup Language,使用DTD(Document Type Definition)来描述数据,主要是为传输和存储数 ...
- Android菜鸟笔记- 获取未安装的APK图标、版本号、包名、名称、是否安装、安装、打开
周末闲来无事,把Android的基础知识拿出来复习复习,今天主题是<获取未安装的APK图标.版本号.包名.名称.是否安装.跳转安装.打开> 一.获取APK图标 通常读取APK的图标能够用, ...
- Oracle 11g 学习3——表空间操作
一.表空间概述 表空间是Oracle中最大的逻辑存储结构,与操作系统中的数据文件相相应: 基本表空间:一般指用户使用的永久性表空间,用于存储用户的永久性数据 暂时表空间: 主要用于存 ...
- mybatis使用generator自己主动生成代码时的类型转换
使用mybatis的generator自己主动生成代码,可是oracle数据库中number(6,2)总是自己主动转成BigDecimal.我想要转成的是float类型 这样就写了一个类型转换器,须要 ...
- When Cyber Security Meets Machine Learning 机器学习 安全分析 对于安全领域的总结很有用 看未来演进方向
链接:http://ucys.ugr.es/jnic2016/docs/MachineLearning_LiorRokachJNIC2016.pdf https://people.eecs.berke ...
- Python 下的 return 关键字
def make_sum(a, b): return ('+', a, b) >> make_sum(1, 2) ('+', 1, 2) 显示地返回一个元组(tuple),当然 retur ...