ClassLoader原理
ClassLoader原理
JVM规范定义了两种类型的类装载器:启动内装载器 (bootstrap) 和用户自定义装载器 (user-defined class loader) 。
一. ClassLoader 基本概念
1 . ClassLoader 分类
类装载器是用来把类(class)装载进JVM的。
JVM规范定义了两种类型的类装载器:启动内装载器 (bootstrap) 和用户自定义装载器 (user-defined class loader) 。
JVM在运行时会产生三个ClassLoader:Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader. Bootstrap是用C++编写的,我们在Java中看不到它,是null,是JVM自带的类装载器,用来装载核心类库,如java.lang.*等。
AppClassLoader 的 Parent 是 ExtClassLoader ,而 ExtClassLoader 的 Parent 为Bootstrap ClassLoader 。
Java 提供了抽象类 ClassLoader ,所有用户自定义类装载器都实例化自 ClassLoader 的子类。 System Class Loader 是一个特殊的用户自定义类装载器,由 JVM 的实现者提供,在编程者不特别指定装载器的情况下默认装载用户类 。系统类装载器可以通过ClassLoader.getSystemClassLoader() 方法得到。
例1,测试你所使用的JVM的ClassLoader
- public class LoaderSample1 {
- public static void main(String[] args) {
- Class c;
- ClassLoader cl;
- cl = ClassLoader.getSystemClassLoader();
- System.out.println(cl);
- while (cl != null ) {
- cl = cl.getParent();
- System.out.println(cl);
- }
- try {
- c = Class.forName( " java.lang.Object " );
- cl = c.getClassLoader();
- System.out.println( " java.lang.Object's loader is " + cl);
- c = Class.forName( " LoaderSample1 " );
- cl = c.getClassLoader();
- System.out.println( " LoaderSample1's loader is " + cl);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
sun.misc.Launcher$AppClassLoader@1a0c10f
sun.misc.Launcher$ExtClassLoader@e2eec8
null
java.lang.Object's loader is null
LoaderSample1's loader is sun.misc.Launcher$AppClassLoader@1a0c10f
第一行表示,系统类装载器实例化自类sun.misc.Launcher$AppClassLoader
第二行表示,系统类装载器的parent实例化自类sun.misc.Launcher$ExtClassLoader
第三行表示,系统类装载器parent的parent为bootstrap
第四行表示,核心类java.lang.Object是由bootstrap装载的
第五行表示,用户类LoaderSample1是由系统类装载器装载的
二. parent delegation模型
从1.2版本开始,Java引入了双亲委托模型,从而更好的保证Java平台的安全。在此模型下,当一个装载器被请求装载某个类时,它首先委托自己的 parent 去装载,若 parent 能装载,则返回这个类所对应的 Class 对象,若 parent 不能装载,则由 parent 的请求者去装载 。
图 1 parent delegation模型
如 图1所示,loader2的parent为loader1,loader1的parent为system class loader。假设loader2被要求装载类MyClass,在parent delegation模型下,loader2首先请求loader1代为装载,loader1再请求系统类装载器去装载MyClass。若系统装载器能成 功装载,则将MyClass所对应的Class对象的reference返回给loader1,loader1再将reference返回给 loader2,从而成功将类MyClass装载进虚拟机。若系统类装载器不能装载MyClass,loader1会尝试装载MyClass,若
loader1也不能成功装载,loader2会尝试装载。若所有的parent及loader2本身都不能装载,则装载失败。
若有一 个能成功装载,实际装载的类装载器被称为定义类装载器,所有能成功返回Class对象的装载器(包括定义类装载器)被称为初始类装载器。如图1所示,假设 loader1实际装载了MyClass,则loader1为MyClass的定义类装载器,loader2和loader1为MyClass的初始类装 载器。
需要指出的是,Class Loader是对象,它的父子关系和类的父子关系没有任何关系。
那么parent delegation模型为什么更安全了?因为在此模型下用户自定义的类装载器不可能装载应该由父亲装载器装载的可靠类,从而防止不可靠甚至恶意的代码代替由父亲装载器装载的可靠代码。实际上,类装载器的编写者可以自由选择不用把请求委托给 parent ,但正如上所说,会带来安全的问题。
类加载器主要分三种:bootstrap(由C语言编写,固化在jvm上)、ExtClassLoader、AppClassLoader。 而bootstrao主要加载rt.jar,ExtClassLoader主要加载Jdk安装路径/jre/lib/ext下的字节码, AppClassLoader主要加载ClassPath下的字节码,类加载器的委托加载原理, 首先加载类一直交给父类加载器加载,一直提交到bootstrap, 当父类加载器加载不到时,在一层层的返回给下一级加载器加载
三.命名空间及其作用
每个类装载器有自己的命名空间,命名空间由所有以此装载器为创始类装载器的类组成。不同命名空间的两个类是不可见的,但只要得到类所对应的Class对象的reference,还是可以访问另一命名空间的类。
例 2演示了一个命名空间的类如何使用另一命名空间的类。在例子中,LoaderSample2由系统类装载器装载,LoaderSample3由自定义的装 载器loader负责装载,两个类不在同一命名空间,但LoaderSample2得到了LoaderSample3所对应的Class对象的 reference,所以它可以访问LoaderSampl3中公共的成员(如age)。
例2不同命名空间的类的访问
- mport java.net. * ;
- import java.lang.reflect. * ;
- public class LoaderSample2 {
- public static void main(String[] args) {
- try {
- String path = System.getProperty( " user.dir " );
- URL[] us = { new URL( " file:// " + path + " /sub/ " )};
- ClassLoader loader = new URLClassLoader(us);
- Class c = loader.loadClass( " LoaderSample3 " );
- Object o = c.newInstance();
- Field f = c.getField( " age " );
- int age = f.getInt(o);
- System.out.println( " age is " + age);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- public class LoaderSample3 {
- static {
- System.out.println( " LoaderSample3 loaded " );
- }
- ;
- }
编译:javac LoaderSample2.java; javac sub/LoaderSample3.java
运行:java LoaderSample2
LoaderSample3 loaded
age is 30
从运行结果中可以看出,在类LoaderSample2中可以创建处于另一命名空间的类LoaderSample3中的对象并可以访问其公共成员age。
运行时包(runtime package)
由 同一类装载器定义装载的属于相同包的类组成了运行时包,决定两个类是不是属于同一个运行时包,不仅要看它们的包名是否相同,还要看的定义类装载器是否相 同。只有属于同一运行时包的类才能互相访问包可见的类和成员。这样的限制避免了用户自己的代码冒充核心类库的类访问核心类库包可见成员的情况。假设用户自 己定义了一个类java.lang.Yes,并用用户自定义的类装载器装载,由于java.lang.Yes和核心类库java.lang.*由不同的装 载器装载,它们属于不同的运行时包,所以java.lang.Yes不能访问核心类库java.lang中类的包可见的成员。
加载原则
加载类用的是全盘负责委托机制。所谓全盘负责,即是当一个classloader加载一个Class的时候,这个Class所依赖的和引用的所有 Class也由这个classloader负责载入,除非是显式的使用另外一个classloader载入
总结
命名空间并没有完全禁止属于不同空间的类的互相访问,双亲委托模型加强了 Java 的安全,运行时包增加了对包可见成员的保护。
ClassLoader原理的更多相关文章
- 【Java核心】ClassLoader原理及其使用
又把博客的皮肤换了换,看着更加简洁舒心一些.前段的知识只是略懂,拿过来就能用,只是自己的审美和设计水平有限,实在难以弄出自己特别满意的东西,也算是小小的遗憾吧!言归正传,由于最近涉及到Java核心的东 ...
- java classloader原理深究
前面已经写过一篇关于java classloader的拙文java classloader原理初探. 时隔几年,再看一遍,觉得有些地方显得太过苍白,于是再来一篇: 完成一个Java类之后,经过java ...
- java的classLoader原理理解和分析
java的classLoader原理理解和分析 学习了:http://blog.csdn.net/tangkund3218/article/details/50088249 ClassNotFound ...
- Java ClassLoader 原理详细分析(转)
转载自:http://www.codeceo.com/article/java-classloader.html 一.什么是ClassLoader? 大家都知道,当我们写好一个Java程序之后,不是管 ...
- 深入分析Java ClassLoader原理
一.什么是ClassLoader? 大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程 ...
- Java ClassLoader 原理详细分析
一.什么是ClassLoader? 大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程 ...
- Android(java)学习笔记106-1:深入分析Java ClassLoader原理
1. 前言: Android中的动态加载机制能更好的优化我们的应用,同时实现动态的更新,这就便于我们管理我们的应用,通过插件化来减轻我们的内存以及CPU消耗,在不发布新版本的情况下能更新某些模块. 当 ...
- Java Classloader原理分析
类的加载过程指通过一个类的全限定名来获取描述此类的二进制字节流,并将其转化为方法区的数据结构,进而生成一个java.lang.Class对象作为方法区这个类各种数据访问的入口.这个过程通过Jav ...
- Android(java)学习笔记45:深入分析Java ClassLoader原理
1. 前言: Android中的动态加载机制能更好的优化我们的应用,同时实现动态的更新,这就便于我们管理我们的应用,通过插件化来减轻我们的内存以及CPU消耗,在不发布新版本的情况下能更新某些模块. 当 ...
随机推荐
- 【OCR技术系列之三】大批量生成文字训练集
放假了,终于可以继续可以静下心写一写OCR方面的东西.上次谈到文字的切割,今天打算总结一下我们怎么得到用于训练的文字数据集.如果是想训练一个手写体识别的模型,用一些前人收集好的手写文字集就好了,比如中 ...
- BZOJ 3198: [Sdoi2013]spring [容斥原理 哈希表]
3198: [Sdoi2013]spring 题意:n个物品6个属性,求有多少不同的年份i,j满足有k个属性对应相等 一开始读错题了,注意是对应相等 第i个属性只能和第i个属性对应 容斥一下 \[ 恰 ...
- nginx隐藏版本号
在实际运用nginx中我们最好将我们的版本号直接隐藏,因为有些版本号的nginx被爆出了漏洞,所以我们为了安全起见,最好将我们的版本号隐藏. 1.对于未安装的nginx我们使用源码编译安装才可以将版本 ...
- RDB持久化
redis是一个内存数据库,所有我们需要将他定时存在磁盘上,如果没有开启AOF,那么会生成RDB文件进行存储,其实就是个二进制文件 RBD文件通过SAVE BGSAVE进行创建, SAVE会阻塞服务器 ...
- 一、scrapy的下载安装---Windows(安装软件太让我伤心了)
写博客就和笔记一样真的很有用,你可以随时的翻阅.爬虫的爬虫原理与数据抓取.非结构化与结构化数据提取.动态HTML处理和简单的图像识别已经学完,就差整理博客了 开始学习scrapy了,所以重新建了个分类 ...
- hiveql函数笔记(二)
1.数据查询 //提高聚合的性能 SET hive.map.aggr=true; SELECT count(*),avg(salary) FROM employees; //木匾不允许在一个查询语句中 ...
- PHPUnit简介及使用
一.PHPUnit是什么? 1.它是一款轻量级的PHP测试框架,地址:http://www.phpunit.cn 2.手册:http://www.phpunit.cn/manual/5.7/zh_cn ...
- php 下载保存文件保存到本地的两种实现方法
这里的下载,指的是 弹出下载提示框. 第一种: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php function downfile() { $filename ...
- 查看Zookeeper服务器状态信息的一些命令
1.Zookeeper服务器当前节点配置信息: echo conf|nc localhost 2181 2.cons:echo cons|nc localhost 2181 输出当前服务器所有客户端连 ...
- mysql中的范式与范式——读<<高性能mysql>>笔记一
对于任何给定的数据库通常都有很多表示方法,从完全的范式化到完全的反范式化,以及两者的折中.在范式化的数据库中,每个事实数据会出现并且只出现一次.相反,在反范式化的数据库中,可能会存储在多个地方. 那什 ...