类加载器(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. 管道实现进程间通讯 、WaitNamedPipe

    一.管道实现进程间通讯 主要的理论知识 1.什么是管道以及分类 管道是两个头的东西,每一个头各连接一个进程或者同一个进程的不同代码,依照管道的类别分有两种管道,匿名的和命名的:依照管道的传输方向分也能 ...

  2. 排序(6)---------归并排序(C语言实现)

    归并排序: 归并操作,也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作.归并排序算法依赖归并操作. 归并操作的步骤例如以下:     (1) 申请空间,使其大小为两个已经排序序列之和.该空 ...

  3. Android开发调试日志工具类[支持保存到SD卡]

    直接上代码: package com.example.callstatus; import java.io.File; import java.io.FileWriter; import java.i ...

  4. Redis 学习笔记五 经常使用php函数

    PHPRedis的安装在这里: http://blog.csdn.net/xundh/article/details/46288277 键值操作 $redis = new Redis(); $redi ...

  5. ABAP 中 Table Control例子

    实现了Table Control的主要的一些功能,可以作为例子参考,实现的功能有是否可编辑切换,选择某一条记录点击按钮显示详细信息,新增记录,删除记录,选择所有记录,选择光标所有记录,取消选择所有,排 ...

  6. 【夯实基础】Spring在ssh中的作用

    尊重版权:http://blog.csdn.net/qjlsharp/archive/2009/03/21/4013255.aspx 写的真不错. 在SSH框假中spring充当了管理容器的角色.我们 ...

  7. html浏览器兼容性的 JavaScript语法

    1.      在FireFox中能够使用与HTML节点对象ID属性值同样的JS变量名称.可是IE中不行. 解决的方法:在命名上区分HTML节点对象ID属性值和JS变量 2.      IE不支持JS ...

  8. Codeforces Round #350 (Div. 2)解题报告

    codeforces 670A. Holidays 题目链接: http://codeforces.com/contest/670/problem/A 题意: A. Holidays On the p ...

  9. Dvtm -- 平铺式终端

    Dvtm -- 平铺式终端_Linux伊甸园开源社区-24小时滚动更新开源资讯,全年无休! Dvtm -- 平铺式终端 关注我们: 如果你使用过 Dwn 或 Awesome 这种平铺式窗口管理器,一定 ...

  10. Android图片与旋转

    拍照后的照片有时被系统旋转,纠正过程例如以下: 1.先读取图片文件被旋转的角度: /** * 通过ExifInterface类读取图片文件的被旋转角度 * @param path : 图片文件的路径 ...