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类载入器的更多相关文章

  1. Java类载入器原理分析

    一:Java虚拟机中能够安装多个类载入器,系统默认是三个基本的类载入器: Bootstrap  ExtClassLoader  AppClassLoader 类载入器也是Java类.由于其它Java类 ...

  2. Java类载入器 ClassLoader的解析

    //參考 : http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类载入器基本概念 类载入器是 Java 语言的一个创新,也是 Ja ...

  3. Java类载入器(一)——类载入器层次与模型

    类载入器   虚拟机设计团队把类载入阶段中的"通过一个类的全限定名来获取描写叙述此类的二进制字节流"这个动作放到Java虚拟机外部去实现.以便让应用程序自己决定怎样去获取所须要的类 ...

  4. Java类载入器(二)——自己定义类载入器

      用户定制自己的ClassLoader能够实现以下的一些应用: 自己定义路径下查找自己定义的class类文件,或许我们须要的class文件并不总是在已经设置好的Classpath以下,那么我们必须想 ...

  5. java类载入器——ClassLoader

    Java的设计初衷是主要面向嵌入式领域,对于自己定义的一些类,考虑使用依需求载入原则.即在程序使用到时才载入类,节省内存消耗,这时就可以通过类载入器来动态载入. 假设你平时仅仅是做web开发,那应该非 ...

  6. 黑马程序猿——Java中的类载入器

    ------- android培训.java培训.期待与您交流! -------- 类载入器 Java虚拟机中能够安装多个类载入器,系统默认三个主要类载入器,每一个类负责载入特定位置的类: BootS ...

  7. 深入研究Java类载入机制

    深入研究Java类载入机制   类载入是Java程序运行的第一步,研究类的载入有助于了解JVM运行过程,并指导开发人员採取更有效的措施配合程序运行. 研究类载入机制的第二个目的是让程序能动态的控制类载 ...

  8. Jboss7类载入器

    1. 类载入器理论知识介绍 类载入器基于Jboss Module,代替了层次类载入环境,避免了当类存在多个版本号时,导致类载入错误. 类载入是基于模块的.必须显示的定义模块依赖.部署也是模块化的,假设 ...

  9. Tomcat类载入器机制(Tomcat源代码解析六)

    要说Tomcat的Classloader机制,我们还得从Bootstrap開始.在BootStrap初始化的时候.调用了org.apache.catalina.startup.Bootstrap#in ...

随机推荐

  1. BAT常问问题总结以及回答(java基础回答一)

    java 基础 八种基本数据类型的大小,以及他们的封装类  答:八种数据类型分别是byte(1字节)-128~127.short(2字节)-32768~32767.char(2字节).int(4字节) ...

  2. 21.QT二进制文件

    #include "mainwindow.h" #include <QApplication> #include <QFile> #include < ...

  3. 限制textfield的文字长度

    -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementSt ...

  4. 解决:[WARNING] fpm_children_bury(), line 215: child 2736 (pool default) exited on signal 15 SIGTERM after 59.588363 seconds from start

    试用Nginx + PHP FastCGI 做WEB服务器,运行了几个月的时间,烦恼的是经常碰到Nginx 502 Bad Gateway 这个问题. 参考了很多修改办法,这个502的问题一直存在,今 ...

  5. tp5页面跳转,空控制器空方法

    namespace app\index\controller; use think\Controller; class Login extends Controller{ //显示html页面 pub ...

  6. T7314 yyy的巧克力(钟)

    题目描述 输入输出格式 输入格式: 如图 输出格式: 如图 输入输出样例 输入样例#1: 如图 输出样例#1: 如图 说明 如图 n*m-1 我们可以这样想,1*1的巧克力一定是由1*2的掰开的 #i ...

  7. PopupWindow实现点击外部不消失

    View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.alert_ip, null); final Po ...

  8. MySQL监控SQL及命中率脚本

    [root@hank-yoon scrips]# vi mysqlstat.sh​​​/export/servers/mysql/bin/mysqladmin -P3306 -uyoon -pyoon ...

  9. Maven配置,使用IntelliJ IDEA和Maven创建Java Web项目

    1. 下载Maven 官方地址:http://maven.apache.org/download.cgi 解压并新建一个本地仓库文件夹 2.配置本地仓库路径   3.配置maven环境变量     4 ...

  10. oracle插入或更新某一个指定列来执行触发器

    表结构: create table TZ_GXSX ( ID VARCHAR2(15), PROJECT VARCHAR2(50), TXYX NUMBER(22) default '0', CDAT ...