类加载器(class loader)用于装载 Java 类到 Java 虚拟机中。一般来说。Java 虚拟机使用 Java 类的方式例如以下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类载入器负责读取
Java 字节代码。并转换成java.lang.Class类的一个实例。每一个这种实例用来表示一个
Java 类。

通过此实例的 newInstance()方法就能够创建出该类的一个对象,也就是万能的Class对象。

Java 中的类载入器大致能够分成两类。一类是系统提供的,另外一类则是由 Java 应用开发者编写的。系统提供的类载入器主要有以下三个:

  • 引导类载入器(bootstrap class loader):它用来载入 Java 的核心库。是用原生代码来实现的。并不继承自 java.lang.ClassLoader
  • 扩展类载入器(extensions class loader):它用来载入 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库文件夹。该类载入器在此文件夹里面查找并载入 Java 类。

  • 系统类载入器(system class loader):它依据 Java 应用的类路径(CLASSPATH)来载入 Java 类。一般来说,Java 应用的类都是由它来完毕载入的。

    能够通过 ClassLoader.getSystemClassLoader()来获取它。

以下这段代码的输出结果能够显示出classloader的树状组织结构。
public class ClassLoaderTest {
public static void main(String[] args){
ClassLoader loader = ClassLoaderTest.class.getClassLoader();
while (loader != null) {
System.out.println(loader.toString());
loader = loader.getParent();
}
}
}

当中loader,toString()方法的返回值等同于以下的表达式:

 getClass().getName() + '@' + Integer.toHexString(hashCode())

程序的输出例如以下:

sun.misc.Launcher$AppClassLoader@70a0afab

sun.misc.Launcher$ExtClassLoader@456d3d51

第一个输出的是 ClassLoaderTree类的类载入器,即系统类载入器。它是 sun.misc.Launcher$AppClassLoader类的实例;第二个输出的是扩展类载入器。是 sun.misc.Launcher$ExtClassLoader类的实例。

须要注意的是这里并没有输出引导类载入器。这是因为有些
JDK 的实现对于父类载入器是引导类载入器的情况,getParent()方法返回 null

在了解了类载入器的树状组织结构之后,以下介绍类载入器的代理模式。

classloader 载入类用的是全盘负责托付机制。所谓全盘负责,即是当一个classloader载入一个Class的时候,这个Class所依赖的和引用的全部
Class也由这个classloader负责载入。除非是显式的使用另外一个classloader载入;托付机制则是先让parent(父)类载入器 (而不是super,它与parent classloader类不是继承关系)寻找。仅仅有在parent找不到的时候才从自己的类路径中去寻找。

此外类载入还採用了cache机制。也就是假设 cache中保存了这个Class就直接返回它,假设没有才从文件里读取和转换成Class,并存入cache。这就是为什么我们改动了Class可是必 须又一次启动JVM才干生效的原因。



每一个ClassLoader载入Class的过程是:

1.检測此Class是否加载过(即在cache中是否有此Class),假设有到8,假设没有到2

2.假设parent classloader不存在(没有parent,那parent一定是bootstrap classloader了),到4。假设存在。到3

3.请求parent classloader加载,假设成功到8。不成功到5

4.请求jvm从bootstrap classloader中加载,假设成功到8

5.寻找Class文件(从与此classloader相关的类路径中寻找)。找到了到6。假设找不到则到7.

6.从文件里加载Class,到8.

7.抛出ClassNotFoundException.

8.返回Class.

总结一下。类载入器的顺序是:

先是bootstrap classloader。然后是extension classloader,最后才是system classloader。这样做的原因是出于安全性的考虑。试想假设system classloader“亲自”载入了一个具有破坏性的“java.lang.System”类的后果吧。

这种托付机制保证了用户即使具有一个这种类, 也把它增加到了类路径中,可是它永远不会被载入。由于这个类总是由bootstrap
classloader来载入的。大家能够运行一下下面的代码:

   System.out.println(System.class.getClassLoader());

将会看到结果是null,这就表明java.lang.System是由bootstrap classloader载入的,由于bootstrap classloader不是一个真正的ClassLoader实例。而是由JVM实现的,正如前面已经说过的。

简而言之,就是自底向上检查类是否已经被载入,然后自顶向下尝试载入类。

值得一提的是tomcat的webappclassloader 这个相当于用户自己定义载入器,为每一个部署在独立tomcat实例上的web应用而创建。该载入器载入的类对于自身应用中的类都是可见的但对于其它web应用不可见,它负责载入以下路径中的类

/WEB-INF/classes

/WEB-INF/lib

和java中的载入类的代理模式方式不同,webapp类载入器採用的是还有一种类载入模式(Servlet 2.4规范9.7.2节 web Application Classloader中建议使用这样的方式),当一个request对象载入一个由webappClassloader负责载入的类时,webappClassloader
将首先在本地库(WEB-INF)进行搜索。与传统的托付给父载入器进行搜索的方式不同。

潜水 java类加载器ClassLoader的更多相关文章

  1. 深入理解Java类加载器(ClassLoader)

    深入理解Java类加载器(ClassLoader) Java学习记录--委派模型与类加载器 关于Java类加载双亲委派机制的思考(附一道面试题) 真正理解线程上下文类加载器(多案例分析) [jvm解析 ...

  2. 深入理解Java类加载器(ClassLoader) (转)

    转自: http://blog.csdn.net/javazejian/article/details/73413292 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Ja ...

  3. Java 类加载器(ClassLoader)

    类加载器 ClassLoader 什么是类加载器? 通过一个类的全限定名来获取描述此类的二进制字节流这个动作放到Java虚拟机外部去实现, 以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代 ...

  4. 浅析java类加载器ClassLoader

    作为一枚java猿,了解类加载器是有必要的,无论是针对面试还是自我学习. 本文从JDK提供的ClassLoader.委托模型以及如何编写自定义的ClassLoader三方面对ClassLoader做一 ...

  5. java类加载器——ClassLoader

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

  6. Java类加载器ClassLoader总结

    JAVA类装载方式,有两种: 1.隐式装载, 程序在运行过程中当碰到通过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中. 2.显式装载, 通过class.forname()等方法,显 ...

  7. Java类加载器(ClassLoader)

    类加载的机制的层次结构 每个编写的”.java”拓展名类文件都存储着需要执行的程序逻辑,这些”.java”文件经过Java编译器编译成拓展名为”.class”的文件,”.class”文件中保存着Jav ...

  8. Java类加载器(死磕5)

    Java类加载器(  CLassLoader )  死磕5:  自定义一个文件系统classLoader 本小节目录 5.1. 自定义类加载器的基本流程 5.2. 入门案例:自定义文件系统类加载器 5 ...

  9. Java类加载器( 死磕9)

    [正文]Java类加载器(  CLassLoader ) 死磕9:  上下文加载器原理和案例 本小节目录 9.1. 父加载器不能访问子加载器的类 9.2. 一个宠物工厂接口 9.3. 一个宠物工厂管理 ...

随机推荐

  1. svn强制用户提交时写日志

    #!/bin/sh REPOS="$1" TXN="$2" SVNLOOK=/usr/bin/svnlook #根据你的SVN目录而定 LOGMSG=`$SVN ...

  2. Qt中无处不在的d指针为何方神圣

    在研究QCoreApplication类的代码时,无意间弄明白了“d_func()”和“d指针”的来源: class Q_CORE_EXPORT QCoreApplication#ifndef QT_ ...

  3. Linux下一个简单的日志系统的设计及其C代码实现

    1.概述 在大型软件系统中,为了监测软件运行状况及排查软件故障,一般都会要求软件程序在运行的过程中产生日志文件.在日志文件中存放程序流程中的一些重要信息, 包括:变量名称及其值.消息结构定义.函数返回 ...

  4. 最佳新秀SSH(十三)——Spring集装箱IOC分析和简单的实现

    时间最近一段时期,"集装箱"这个词一直萦绕在我的耳边,连吃饭.睡在我的脑海里蹦来蹦去的. 由于这几天的交流时间.讨论,对于理解容器逐渐加深. 理论上的东西终归要落实到实践,今天就借 ...

  5. 【ThinkingInC++】52、函数内部的静态变量

    /** * 书本:[ThinkingInC++] * 功能:函数内部的静态变量 * 时间:2014年9月17日18:06:33 * 作者:cutter_point */ #include " ...

  6. ipsec vpn私网数据大量掉包问题

    周四出现了一个很奇葩的问题,所有的站点的VPN通信都是正常的,唯独郑州节点和中心节点的私网数据长ping掉包量达到20%左右,在中心节点ping郑州节点公网IP没有发现掉包问题,故障排除如下: 1.测 ...

  7. LeetCode——Search in Rotated Sorted Array II

    Follow up for "Search in Rotated Sorted Array": What if duplicates are allowed? Would this ...

  8. JAVA实现Shell排序

    Shell排序可以理解为插入排序的变种,它充分利用了插入排序的两个特点: (1). 当数据规模小的时候非常高效. (2). 当给定数据已经有序时的时间代价为O(N) 所以,Shell排序每次把数据分成 ...

  9. TMG 2010 VPN配置

    微软的ISA 到2006以后就叫TMG了,上周在公司的服务器上安装测试了下,虽然增加了很多功能,但是主要功能上和ISA 2004差不多,最近在部署L2TP VPN,由于防火墙带的远程访问VPN为纯的L ...

  10. dsbskrhkme看么哦么

    http://pan.baidu.com/share/link?shareid=3011665141&uk=338692646&third=15                http ...