Java类加载器( 死磕 4)
【正文】Java类加载器( CLassLoader ) 死磕 之4:
神秘的双亲委托机制
本小节目录
4.1. 每个类加载器都有一个parent父加载器
4.2. 类加载器之间的层次关系
4.3. 类的加载次序
4.4 双亲委托机制原理与沙箱机制
4.5. forName方法和loadClass方法的关系
4.6. 使用组合而不用继承
4.7. 各种不同的类加载途径
4.1.每个类加载器都有一个parent父加载器
每个类加载器都有一个parent父加载器,比如加载SystemConfig.class是由AppClassLoader完成,那么AppClassLoader也有一个父加载器,怎么样获取呢?很简单,通过getParent方法。
这里写了一个公共的函数,来取得一个类的加载器的双亲树。代码如下:
/**
* 迭代,显示class loader 和 父加载器
*/
public static void showLoaderTree(ClassLoader loader) {
while (loader != null) {
Logger.info(loader.toString());
loader = loader.getParent();
}
}
这个函数,不断循环,向上显示了父亲、父亲的父亲、父亲的父亲的父亲..,直到为空。
这样,就展示了一棵类加载器的双亲树。
使用上面的函数,演示代码如下:
private static void loaderTreeDemo() throws ClassNotFoundException
{
String className = "com.crazymakercircle.config.SystemConfig";
Class<?> aClass = Class.forName(className);
ClassLoader aLoader=aClass.getClassLoader();
Logger.info("加载器:"+aLoader.toString());
ClassLoaderUtil.showLoaderTree(aLoader);
}
案例路径:com.crazymakercircle.classLoaderDemo.base.ParentTreeDemo
案例提示:无编程不创客、无案例不学习。切记,一定要跑案例哦
案例结果如下:
loaderTreeDemo |> 加载器:sun.misc.Launcher$AppClassLoader@18b4aac2 showLoaderTree |> sun.misc.Launcher$AppClassLoader@18b4aac2 showLoaderTree |> sun.misc.Launcher$ExtClassLoader@6fdb1f78
这个说明,当前加载器类型为AppClassLoader,而AppClassLoader父加载器类是ExtClassLoader。ExtClassLoader的父加载器,又是谁呢? 没有了打印。
parent为空表示什么意思呢?
我们先来梳理一下加载器之间的层次关系。
4.2. 类加载器之间的层次关系
下面展示一下Bootstrap 启动类加载器、Extention标准扩展类加载器和App应用类加载器三者之间的关系。
大致整理了如下类似的一幅图片:
每一个加载器看护一块自己的地盘。 启动Bootstrap 看护的是核心中的核心地盘。
前面讲到,ExtClassLoader的父加载器为空。而上图中,ExtClassLoader的父加载器是Bootstrap 启动类加载器。
实际上,如果一个加载器的parent为空,其父亲加载器就是Bootstrap 启动类加载器。
如果没有特别的设置,自定义加载的parent,默认为App应用加载器。
4.3. 类的加载次序
loadClass 关键源代码,已经在前面有介绍。
下面用一张图,对于类的加载次序,做进一步的介绍。
一般场景下,加载一个类,是从AppClassLoader开始的。
基本的步骤如下:
(1)AppClassLoader查找资源时,不是首先查看自己的地盘是否有这个字节码文件,而是直接委托给父加载器ExtClassLoader。当然,这里有一个假定,就是在AppClassLoader的缓存中,没有找到目标class。比方说,第一次加载一个目标类,这个类是不会在缓存的。
(2)ExtClassLoader查找资源时,也不是首先查看自己的地盘是否有这个字节码文件,而是直接委托给父加载器BootstrapClassLoader。
(3)如果父加载器BootstrapClassLoader在其地盘找到,并且加载成功,则直接返回了;反过来,如果在JVM的核心地盘——%sun.boot.class.path% 中没有找到。则回到ExtClassLoader查找其地盘。
(4)如果父加载器ExtClassLoader在自己的地盘找到,并且加载成功,也直接返回了;反过来,如果在ExtClassLoader的地盘——%java.ext.dirs% 中没有找到。则回到AppClassLoader自己的地盘。
(5)于是乎,逗了一大圈,终于回到了自己的地盘。还附带了两条件,就是前面的老大们没有搞定,否则也没有AppClassLoader啥事情了。
(6)AppClassLoader在自己的地盘找到,这个地盘就是%java.class.path%路径下查找。找到就返回。
(7)最终,如果没有找到,就抛出异常了。
这个过程,就是一个典型的双亲委托机制的一次执行流程。
什么是双亲委托机制呢?
4.4. 双亲委托机制原理与沙箱机制
双亲委派模型的的原理是:
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中。只有当父加载器反馈自己无法完全这个加载请求时,子加载器才会尝试自己去加载。
为什么要使用这种双亲委托模式呢?
因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。
双亲委托机制,也就构成了JVM 的类的沙箱机制。
沙箱机制是由基于双亲委派机制上采取的一种JVM的自我保护机制,假设你要写一个java.lang.String 的类,由于双亲委派机制的原理,此请求会先交给Bootstrap试图进行加载,但是Bootstrap在加载类时首先通过包和类名查找rt.jar中有没有该类,有则优先加载rt.jar包中的类,因此就保证了java的运行机制不会被破坏。
4.5. forName方法和loadClass方法的关系
说到这里,顺便回答一下前面提出的一个问题。
前面提到,explicit显式方式,又分两种方式:
一是:java.lang.Class的forName()方法;
二是:java.lang.ClassLoader的loadClass()方法。
二者的区别和联系是什么呢?
首先看联系:
Class.forName使用的是调用者的类加载器loadClass()方法来加载类的。
其次看区别。
当调用Class.forName(String)载入class时执行,会完整的完成前面提到的五步工作,就是加载、验证、准备、解析、初始化。
如果调用ClassLoader.loadClass(String)载入class时,会执行加载、验证、准备、解析的前面四步,并不会执行第五步——初始化。这是,类的static块没有被执行。需要在第一次实例化时执行,比如第一次执行 Class.newInstance() 操作时。
4.6. 使用组合而不用继承
4.7. 各种不同的类加载途径
Java类不是一次性加载的,而是动态被加载到内存。这是java的一大特点,也称为运行时绑定,或动态绑定。
除了通过Java内置的三大加载器,从JVM中系统属性中设置的三大地盘加载Java类,还存在以下的获取Class文件途径:
(1)从ZIP包中读取。很常见,最终成为日后JAR,WAR,EAR格式的基础。
(2)从网络中获取。这种场景典型的就是Applet。
(3)运行时计算生成。典型的情景就是java动态代理技术。
(4)从其他文件中生成。典型场景是JSP应用,即由JSP文件生成对应的Class类。
(5)从不方便加入到%java.class.path%其他的文件目录获取。
如何实现以上的途径呢?
具体的方法是:通自定义的类加载器,去加载其他途径的类。
源码:
代码工程: classLoaderDemo.zip
下载地址:在疯狂创客圈QQ群文件共享。
疯狂创客圈:如果说Java是一个武林,这里的聚集一群武痴, 交流编程体验心得
QQ群链接:疯狂创客圈QQ群
无编程不创客,无案例不学习。 一定记得去跑一跑案例哦
类加载器 全目录
5. 入门案例:自定义一个文件系统的自定义classLoader
8. 高级案例1:使用ASM技术,结合类加载器,解密AOP原理
Java类加载器( 死磕 4)的更多相关文章
- Java类加载器(死磕 1-2)
Java类加载器( CLassLoader ) 死磕 1.2: 导入 & 类加载器分类 本小节目录 1.导入 1.1. 从class文件的载入开始 1.2. 什么是类加载器 2. JA ...
- Java类加载器(死磕5)
Java类加载器( CLassLoader ) 死磕5: 自定义一个文件系统classLoader 本小节目录 5.1. 自定义类加载器的基本流程 5.2. 入门案例:自定义文件系统类加载器 5 ...
- Java类加载器( 死磕9)
[正文]Java类加载器( CLassLoader ) 死磕9: 上下文加载器原理和案例 本小节目录 9.1. 父加载器不能访问子加载器的类 9.2. 一个宠物工厂接口 9.3. 一个宠物工厂管理 ...
- Java类加载器( 死磕7)
[正文]Java类加载器( CLassLoader )死磕7: 基于加密的自定义网络加载器 本小节目录 7.1. 加密传输Server端的源码 7.2. 加密传输Client端的源码 7.3. 使 ...
- Java类加载器( 死磕8)
[正文]Java类加载器( CLassLoader ) 死磕 8: 使用ASM,和类加载器实现AOP 本小节目录 8.1. ASM字节码操作框架简介 8.2. ASM和访问者模式 8.3. 用于增 ...
- Java类加载器( 死磕 6)
[正文]Java类加载器( CLassLoader )死磕 6: 自定义网络类加载器 本小节目录 6.1. 自定义网络类加载器的类设计 6.2. 文件传输Server端的源码 6.3. 文件传输C ...
- Java类加载器(死磕3)
[正文]Java类加载器( CLassLoader ) 死磕3: 揭秘 ClassLoader抽象基类 本小节目录 3.1. 类的加载分类:隐式加载和显示加载 3.2. 加载一个类的五步工作 3. ...
- java笔记--理解java类加载器以及ClassLoader类
类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制 ...
- java类加载器深入研究
看了下面几篇关于类的加载器的文章,豁然开朗.猛击下面的地址开始看吧. Java类加载原理解析 深入探讨 Java 类加载器 分析BootstrapClassLoader/ExtClassLo ...
随机推荐
- phthon入门介绍
1.基本的python语法 2.python爬虫 3.基本的数据分析 4.做网站 5.做机器学习 1.python简介: Python 是一种解释型语言: 这意味着开发过程中没有了编译这个环节.类似于 ...
- JVM指令详解(下)
九.自增减指令 该指令用于对本地(局部)变量进行自增减操作.该指令第一参数为本地变量的编号,第二个参数为自增减的数量. 比如对于代码: int d=10; d++; d ...
- 转 Centos下安装apahce的configure: error: APR not found. Please read the documentation解决办法
转自: http://www.cnblogs.com/Anker/p/3355573.html 今天从Apache官网上http://httpd.apache.org/下载httpd web服务器,由 ...
- #pragma用法
#pragma是一种预处理指令,作用是设定编译器的状态或者是指示编译器完成一些特定的动作. 其格式一般为:#pragma Para.其中Para为参数.下面是一些常见用法. 1.message ——在 ...
- hdu 1254(搜索题)
推箱子 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- String()和.toString()的区别
一.相同点:都可以转为字符串类型: 二.不同点: 1..toString() :null.toString()和undefined.toString() 程序报错误; 2..toString(): . ...
- 牛客网 牛客小白月赛1 A.简单题-控制输出格式setiosflags()函数+setprecision()函数
水一水博客,都不好意思写这篇博客,毕竟已经不是大一的了. 难得能把一整套题都写出来(日常智障).但是在这里不写G题あなたの蛙は旅⽴っています的题解. 有毒,G题关了流同步只能过94%的样例,说我运行超 ...
- IntelliJ IDEA提示:Class JavaLaunchHelper is implemented in both的错误解决
这个错误是Mac下特有的,并且据说是一个老Bug,不影响使用. 修复方法: Help->Edit Custom Properties,没有这个properties文件的话,IDEA会提示创建,然 ...
- Linux 在VMware中搭建CentOS6.5虚拟机
原文:http://www.cnblogs.com/PurpleDream/p/4263465.html Linux 在VMware中搭建CentOS6.5虚拟机 前言: 本文主要是我在大家 ...
- 主流浏览器js 引擎内核市场份额attialx总结vOa9
原文: http://blog.csdn.net/attilax/article/details/40016... 时间: 2014-10-12 atitit.. 主流浏览器 js 引擎 内核 市场份 ...