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. <LeetCode OJ> 100. Same Tree

    100. Same Tree Total Accepted: 100129 Total Submissions: 236623 Difficulty: Easy Given two binary tr ...

  2. MySQL具体解释(8)----------MySQL线程池总结(二)

    这篇文章是对上篇文章的一个补充,主要环绕下面两点展开.one-connection-per-thread的实现方式以及线程池中epoll的使用. one-connection-per-thread 依 ...

  3. 关于vue 自定义组件的写法与用法

    最近在网上看到很多大神都有写博客的习惯,坚持写博客不但可以为自己的平时的学习做好记录积累 无意之中也学还能帮助到一些其他的朋友所以今天我也注册一个账号记录一下学习的点滴!当然本人能力实在有限写出的文章 ...

  4. iOS判断一些权限是否被禁止

    iOS中经常会遇到访问相册.相机.麦克疯.蓝牙.以及推送等权限,所以每次我们要使用这些权限是都要记得查看用户是否允许了,如果用户禁止了你的访问权限,你仍然去调取相册或者相机等,那么就会先出现下面的这个 ...

  5. Linux就该这么学 20181008(第十三章BIND)

    参考链接https://www.linuxprobe.com Bind提供域名解析服务 DNS Domin Name Server 域名解析服务 功能模式 .正向解析,将域名解析为IP地址 .反向解析 ...

  6. Reusability1

    Reusability 1. 复用的层面 1.1 代码级别复用 顾名思义,代码复用就是把代码都搬过来,这是最主要的复用 1.1.1 白盒复用 白盒的意思就是里面的东西我们都知道是什么,具体实现的方式也 ...

  7. POJ 2392 DP

    题目大意:有一头奶牛要上太空,他有很多种石头,每种石头的高度是hi,但是不能放到ai之上的高度,并且这种石头有ci个 将这些石头叠加起来,问能够达到的最高高度. 题意转载自:http://blog.c ...

  8. KCP kcptun

    简介 KCP是一个快速可靠协议,能以比 TCP浪费10%-20%的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果.纯算法实现,并不负责底层协议(如UDP)的收发,需要使用者 ...

  9. js闭包概念

    含义:闭包是一个概念,它描述了函数执行完毕内存释放后,依然内存驻留的一个现象,只要把握这个核心概念,闭包就不难理解了 function a(){      var i=0;      function ...

  10. http接口服务方结合策略模式实现总结

    在项目中,我们经常会使用到http+xml的接口,而且不仅仅的是一个,可能会有多个http的接口需要实时的交互.但是http接口的接收消息的公共部分是一样的,只有每个接口的报文解析和返回报文是不同的, ...