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

  1. public   class  LoaderSample1 {
  2. public   static   void  main(String[] args) {
  3. Class c;
  4. ClassLoader cl;
  5. cl  =  ClassLoader.getSystemClassLoader();
  6. System.out.println(cl);
  7. while  (cl  !=   null ) {
  8. cl  =  cl.getParent();
  9. System.out.println(cl);
  10. }
  11. try  {
  12. c  =  Class.forName( " java.lang.Object " );
  13. cl  =  c.getClassLoader();
  14. System.out.println( " java.lang.Object's loader is  "   +  cl);
  15. c  =  Class.forName( " LoaderSample1 " );
  16. cl  =  c.getClassLoader();
  17. System.out.println( " LoaderSample1's loader is  "   +  cl);
  18. }  catch  (Exception e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. }

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不同命名空间的类的访问

  1. mport  java.net. * ;
  2. import  java.lang.reflect. * ;
  3. public   class  LoaderSample2 {
  4. public   static   void  main(String[] args) {
  5. try  {
  6. String path  =  System.getProperty( " user.dir " );
  7. URL[] us  =  { new  URL( " file:// "   +  path  +   " /sub/ " )};
  8. ClassLoader loader  =   new  URLClassLoader(us);
  9. Class c  =  loader.loadClass( " LoaderSample3 " );
  10. Object o  =  c.newInstance();
  11. Field f  =  c.getField( " age " );
  12. int  age  =  f.getInt(o);
  13. System.out.println( " age is  "   +  age);
  14. }  catch  (Exception e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. }
  1. public   class  LoaderSample3 {
  2. static  {
  3. System.out.println( " LoaderSample3 loaded " );
  4. }
  5. ;
  6. }

编译: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原理的更多相关文章

  1. 【Java核心】ClassLoader原理及其使用

    又把博客的皮肤换了换,看着更加简洁舒心一些.前段的知识只是略懂,拿过来就能用,只是自己的审美和设计水平有限,实在难以弄出自己特别满意的东西,也算是小小的遗憾吧!言归正传,由于最近涉及到Java核心的东 ...

  2. java classloader原理深究

    前面已经写过一篇关于java classloader的拙文java classloader原理初探. 时隔几年,再看一遍,觉得有些地方显得太过苍白,于是再来一篇: 完成一个Java类之后,经过java ...

  3. java的classLoader原理理解和分析

    java的classLoader原理理解和分析 学习了:http://blog.csdn.net/tangkund3218/article/details/50088249 ClassNotFound ...

  4. Java ClassLoader 原理详细分析(转)

    转载自:http://www.codeceo.com/article/java-classloader.html 一.什么是ClassLoader? 大家都知道,当我们写好一个Java程序之后,不是管 ...

  5. 深入分析Java ClassLoader原理

    一.什么是ClassLoader? 大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程 ...

  6. Java ClassLoader 原理详细分析

    一.什么是ClassLoader? 大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程 ...

  7. Android(java)学习笔记106-1:深入分析Java ClassLoader原理

    1. 前言: Android中的动态加载机制能更好的优化我们的应用,同时实现动态的更新,这就便于我们管理我们的应用,通过插件化来减轻我们的内存以及CPU消耗,在不发布新版本的情况下能更新某些模块. 当 ...

  8. Java Classloader原理分析

       类的加载过程指通过一个类的全限定名来获取描述此类的二进制字节流,并将其转化为方法区的数据结构,进而生成一个java.lang.Class对象作为方法区这个类各种数据访问的入口.这个过程通过Jav ...

  9. Android(java)学习笔记45:深入分析Java ClassLoader原理

    1. 前言: Android中的动态加载机制能更好的优化我们的应用,同时实现动态的更新,这就便于我们管理我们的应用,通过插件化来减轻我们的内存以及CPU消耗,在不发布新版本的情况下能更新某些模块. 当 ...

随机推荐

  1. phpstorm中使用xdebug配置cli模式的调试

    这里略去xdebug的安装,安装很简单可以下载源码包,动态编译进去! 环境: Dev 服务器(IP:192.168.2.100),安装phpstorm,用来做开发任务! Server服务器(IP:19 ...

  2. 洛谷 [P2762] 太空飞行计划问题

    最大权闭合子图 胡伯涛论文真是个好东西.jpg 求一个有向图的最大权闭合子图,常应用于有先决条件的最优化问题中 将所有正权点与源点相连,容量为点权; 将所有负权点与汇点相连,容量为点权的相反数; 将原 ...

  3. D 区间求和 [数学 树状数组]

    D 区间求和 题意:求 \[ \sum_{k=1}^n \sum_{l=1}^{n-k+1} \sum_{r=l+k-1}^n 区间前k大值和 \] 比赛时因为被B卡了没有深入想这道题 结果B没做出来 ...

  4. 洛谷4月月赛R2

    洛谷4月月赛R2 打酱油... A.koishi的数学题  线性筛约数和就可以\(O(N)\)了... #include <iostream> #include <cstdio> ...

  5. [Sdoi2017]数字表格 [莫比乌斯反演]

    [Sdoi2017]数字表格 题意:求 \[ \prod_{i=1}^n \prod_{j=1}^m f[(i,j)] \] 考场60分 其实多推一步就推倒了... 因为是乘,我们可以放到幂上 \[ ...

  6. Uva 11077 Find the Permutations [置换群 DP]

    题意: 给定$n$和$k$,问有多少排列交换$k$次能变成升序 $n \le 21$ $uva$貌似挂掉了$vjudge$上一直排队 从某个排列到$1,2,...,n$和从$1,2,...,n$到某个 ...

  7. Django搭建博客网站(三)

    Django搭建博客网站(三) 第三篇主要记录view层的逻辑和template. Django搭建博客网站(一) Django搭建博客网站(二) 结构 网站结构决定我要实现什么view. 我主要要用 ...

  8. ASP.NET Core 发布 centos7 配置守护进程

    ASP.NET Core应用程序发布linux在shell中运行是正常的.可一但shell关闭网站也就关闭了,所以要配置守护进程, 用的是Supervisor,本文主要记录配置的过程和过程遇到的问题 ...

  9. git命令行工作的正确姿势

    git命令行创建并提交新分支到mater分支的常规步骤 git branch new_branch git status 查看修改的文件 git add changed_files git commi ...

  10. LNMP搭建03 -- 编译安装PHP

    [编译安装PHP]  为了顺利安装PHP,先安装下面这些: [CentOS 编译 PHP 前要做的事情] yum install -y gcc gcc-c++  make zlib zlib-deve ...