潜水 java类加载器ClassLoader
类加载器(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()
来获取它。
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的更多相关文章
- 深入理解Java类加载器(ClassLoader)
深入理解Java类加载器(ClassLoader) Java学习记录--委派模型与类加载器 关于Java类加载双亲委派机制的思考(附一道面试题) 真正理解线程上下文类加载器(多案例分析) [jvm解析 ...
- 深入理解Java类加载器(ClassLoader) (转)
转自: http://blog.csdn.net/javazejian/article/details/73413292 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Ja ...
- Java 类加载器(ClassLoader)
类加载器 ClassLoader 什么是类加载器? 通过一个类的全限定名来获取描述此类的二进制字节流这个动作放到Java虚拟机外部去实现, 以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代 ...
- 浅析java类加载器ClassLoader
作为一枚java猿,了解类加载器是有必要的,无论是针对面试还是自我学习. 本文从JDK提供的ClassLoader.委托模型以及如何编写自定义的ClassLoader三方面对ClassLoader做一 ...
- java类加载器——ClassLoader
Java的设计初衷是主要面向嵌入式领域,对于自定义的一些类,考虑使用依需求加载原则,即在程序使用到时才加载类,节省内存消耗,这时即可通过类加载器来动态加载. 如果你平时只是做web开发,那应该很少会跟 ...
- Java类加载器ClassLoader总结
JAVA类装载方式,有两种: 1.隐式装载, 程序在运行过程中当碰到通过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中. 2.显式装载, 通过class.forname()等方法,显 ...
- Java类加载器(ClassLoader)
类加载的机制的层次结构 每个编写的”.java”拓展名类文件都存储着需要执行的程序逻辑,这些”.java”文件经过Java编译器编译成拓展名为”.class”的文件,”.class”文件中保存着Jav ...
- Java类加载器(死磕5)
Java类加载器( CLassLoader ) 死磕5: 自定义一个文件系统classLoader 本小节目录 5.1. 自定义类加载器的基本流程 5.2. 入门案例:自定义文件系统类加载器 5 ...
- Java类加载器( 死磕9)
[正文]Java类加载器( CLassLoader ) 死磕9: 上下文加载器原理和案例 本小节目录 9.1. 父加载器不能访问子加载器的类 9.2. 一个宠物工厂接口 9.3. 一个宠物工厂管理 ...
随机推荐
- unity中怎样获取全部子物体的组件
public GameObject[] obj; void Awake() { for (int i = 0; i < obj.Length; i++) ...
- Linux vmstat命令详解
vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况.这个命令是我查看Linux/Unix最 ...
- Linux入门基础 #10:命令行文本处理工具
本文出自 http://blog.csdn.net/shuangde800 ------------------------------------------------------------ ...
- UVA 10622 - Perfect P-th Powers(数论)
UVA 10622 - Perfect P-th Powers 题目链接 题意:求n转化为b^p最大的p值 思路:对n分解质因子,然后取全部质因子个数的gcd就是答案,可是这题有个坑啊.就是输入的能够 ...
- 虚拟机centOS中安装Redis,主机Redis Destop Manager不能访问虚拟机Redis server的解决方案
今天在学些redis的时候碰到个问题,发现主机Redis Destop Manager不能访问虚拟机Redis server的解决方案,找了一些网上的资料,原因可能有两个,整理记录下来: 1. Red ...
- hdu1116--解题报告--初步了解欧拉回路
由题目意思..我们只要把n个字符串的首尾字母看作是点,这个字符串看着边来处理就可以啦...将题目的案例图形化如下: 那么接着就是欧拉路径和欧拉回路判断,我们这里用并査集来判断图是不是连通的,然后根据有 ...
- No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=arm64, VALID_ARCHS=armv7 armv7s)
问题: No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=arm64, VALID_ARCHS=armv7 armv ...
- 开源mp3播放器--madplay 编译和移植 简记
madplay是一款开源的mp3播放器. http://madplay.sourcearchive.com/ 下面简单记录一下madplay的编译与移植到ARM开发板上的过程 一.编译x86版本的ma ...
- Typings实现智能
在Visual Studio Code中通过Typings实现智能提示功能 前言 我们知道在IDE中代码的智能提示几乎都是标配,虽然一些文本编辑器也有一些简单的提示,但这是通过代码片段提供的.功能 ...
- vc 基于对话框多线程编程实例——线程之间的通信
vc基于对话框多线程编程实例——线程之间的通信 实例: