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. ios网络学习------3 用非代理方法实现异步post请求

    #pragma mark - 这是私有方法.尽量不要再方法中直接使用属性,由于一般来说属性都是和界面关联的,我们能够通过參数的方式来使用属性 #pragma mark post登录方法 -(void) ...

  2. 交叉编译faac共享库

    作者:咕唧咕唧liukun321 来自:http://blog.csdn.net/liukun321 Advanced Audio Coding.一种专为声音数据设计的文件压缩格式,与Mp3不同,它採 ...

  3. jQuery验证所有输入合法后才干提交

    大学三年里所有在专注后台编码.学会不知多少种,servlet.ssh,springMVC,web.py...... 最后每次碰到前端自己要写点东西就满目愁抑, 干脆自己好好理解一段前端代码, 特地拿出 ...

  4. __FUNCTION__, __LINE__ 有助于debug的宏定义

    __FUNCTION__, __LINE__ 今天无意之间看到一段代码,里面有这样一个片段: if (!interface) { err ("%s - error, can't find d ...

  5. [C++设计模式] iterator 迭代器模式

    迭代器模式定义:提供一种方法顺序訪问一个聚合对象中各个元素,而又不须要暴露该对象. 迭代器分内部迭代器和外部迭代器.内部迭代器与对象耦合紧密,不推荐使用. 外部迭代器与聚合容器的内部对象松耦合,推荐使 ...

  6. 7.matlab字符串分析

    1 字符串处理函数 clc; clear all; str='My name is Robin.'; disp(str); %字符串的输出 str_size=size(str) %字符串的长度 str ...

  7. ubuntu 绘制lenet网络结构图遇到的问题汇总

    Couldn't import dot_parser, loading of dot files will not be possible的问题 1 .sudo pip uninstall pypar ...

  8. JQuery事件绑定,bind与on区别

    jquery事件绑定bind:向匹配元素添加一个或多个事件处理器 $(selector).bind("click",data,function); live:向当前或未来的匹配元素 ...

  9. SQL Server-聚焦使用索引和查询执行计划

    前言 上一篇我们讲了聚集索引对非聚集索引的影响,对数据库一直在强调的性能优化,所以这一节我们统筹讲讲利用索引来看看查询执行计划是怎样的,简短的内容,深入的理解,Always to review the ...

  10. linux拷贝文件

    linux之cp/scp命令+scp命令详解 2011-03-09 17:27:22|  分类: Linux |  标签:linux  cp  scp  commond   |字号 订阅   名称:c ...