Java 类加载体系之 ClassLoader 双亲委托机制

java 是一种类型安全的语言,它有四类称为安全沙箱机制的安全机制来保证语言的安全性,这四类安全沙箱分别是:

  • 类加载体系
  • .class文件检验器
  • 内置于java虚拟机的安全特性
  • 安全管理器及javaAPI

类的加载体系如下

java 程序中的 .java 文件编译完会生成 .class 文件,而 .class 文件就是通过被称为类加载器的 ClassLoader加载的,而 ClassLoder 在加载过程中会使用“双亲委派机制”来加载 .class 文件,先上图:

BootStrapClassLoader :启 动 类 加 载 器 ,该ClassLoader 是 jvm 在 启 动 时 创 建 的 ,用 于 加载$JAVA_HOME$/jre/lib 下面的类库(或者通过参数-Xbootclasspath 指定)。由于启动类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不能直接通过引用进行操作。

ExtClassLoader:扩展类加载器,该 ClassLoader 是在 sun.misc.Launcher 里作为一个内部类 ExtClassLoader 定义的(即 sun.misc.Launcher$ExtClassLoader),ExtClassLoader 会加载 $JAVA_HOME/jre/lib/ext 下的类库(或者通过参数-Djava.ext.dirs 指定)。

AppClassLoader:应用程序类加载器,该 ClassLoader 同样是在 sun.misc.Launcher 里作为一个内部AppClassLoader 定义的(即 sun.misc.Launcher$AppClassLoader),AppClassLoader 会加载 java 环境变量 CLASSPATH 所指定的路径 下的类库,而 CLASSPATH 所指定的 路 径 可 以 通 过System.getProperty("java.class.path")获取;当然,该变量也可以覆盖,可以使用参数-cp,例如:java -cp 路径 (可以指定要执行的 class 目录)。

CustomClassLoader:自定义类加载器,该 ClassLoader 是指我们自定义的 ClassLoader,比如 tomcatStandardClassLoader 属于这一类;当然,大部分情况下使用 AppClassLoader 就足够了。

前面谈到了 ClassLoader 的几类加载器,而 ClassLoader 使用双亲委派机制来加载 class 文件的。ClassLoader的双亲委派机制是这样的(这里先忽略掉自定义类加载器 CustomClassLoader):

1)当 AppClassLoader 加载一个 class 时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器 ExtClassLoader 去完成。

2)当 ExtClassLoader 加载一个 class 时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader 去完成。

3)如果 BootStrapClassLoader 加载失败(例如在$JAVA_HOME$/jre/lib 里未查找到该 class),会使用ExtClassLoader 来尝试加载;

4)若 ExtClassLoader 也加载失败,则会使用 AppClassLoader 来加载,如果 AppClassLoader 也加载失败,则会报出异常 ClassNotFoundException。

下面贴下 ClassLoader 的 loadClass(String name, boolean resolve)的源码:

1.protected synchronized Class<?> loadClass(String name, boolean resolve)
2.  throws  ClassNotFoundException  {
3.  //  首先找缓存是否有 class
4.  Class  c  =  findLoadedClass(name);
5.  if  (c  ==  null)  {
6.  //没有判断有没有父类
7.  try  {
8.  if  (parent  !=  null)  {
9.  //有的话,用父类递归获取 class
10. c = parent.loadClass(name, false);
11. } else {
12. //没有父类。通过这个方法来加载
13. c = findBootstrapClassOrNull(name);
14. }
15. } catch (ClassNotFoundException e) {
16. // ClassNotFoundException thrown if class not found
17. // from the non-null parent class loader
18. }
19. if (c == null) {
20. //  如果还是没有找到,调用 findClass(name)去找这个类
21. c = findClass(name);
22. }
23. }
24. if (resolve) {
25. resolveClass(c);
26. }
27. return c;
28.  }

代码很明朗:首先找缓存(findLoadedClass),没有的话就判断有没有 parent,有的话就用 parent 来递归的 loadClass,然而 ExtClassLoader 并没有设置 parent,则会通过 findBootstrapClassOrNull 来加载 class,而findBootstrapClassOrNull 则会通过 JNI 方法”private native Class findBootstrapClass(String name)“来使用 BootStrapClassLoader 来加载 class。

然后如果 parent 未找到 class,则会调用 findClass 来加载 class,findClass 是一个 protected 的空方法,可以覆盖它以便自定义 class 加载过程。另 外 ,虽 然 ClassLoader 加载类是使用 loadClass 方法 ,但 是 鼓 励 用 ClassLoader 的 子 类 重 写 findClass(String),而不是重写 loadClass,这样就不会覆盖了类加载默认的双亲委派机制。

双亲委派托机制为什么安全

举个例子,ClassLoader 加载的 class 文件来源很多,比如编译器编译生成的 class、或者网络下载的字节码。而一些来源的 class 文件是不可靠的,比如我可以自定义一个 java.lang.Integer 类来覆盖 jdk 中默认的 Integer 类,例如下面这样:

1. package java.lang;
2. public class Integer {
3.   public Integer(int value) {
4.      System.exit(0);
5.  }
6. }

初始化这个 Integer 的构造器是会退出 JVM,破坏应用程序的正常进行,如果使用双亲委派机制的话该 Integer 类永远不会被调用,以为委托 BootStrapClassLoader 加载后会加载 JDK 中的 Integer 类而不会加载自定义的这个,可以看下下面这测试个用例:

1.public static void main(String...  args) {
2.  Integer i = new Integer(1);
3.  System.err.println(i);
4.}

执行时 JVM 并未在 new Integer(1)时退出,说明未使用自定义的 Integer,于是就保证了安全性。

转载于:https://www.cnblogs.com/caotao0918/p/10734505.html

Java 类加载体系之 ClassLoader 双亲委托机制相关推荐

  1. java类加载-ClassLoader双亲委派机制

    "类加载体系"及ClassLoader双亲委派机制.java程序中的 .java文件编译完会生成 .class文件,而 .class文件就是通过被称为类加载器的ClassLoade ...

  2. java安全沙箱(一)之ClassLoader双亲委派机制

    java是一种类型安全的语言,它有四类称为安全沙箱机制的安全机制来保证语言的安全性,这四类安全沙箱分别是: 类加载体系 .class文件检验器 内置于Java虚拟机(及语言)的安全特性 安全管理器及J ...

  3. 【Android 逆向】类加载器 ClassLoader ( 启动类加载器 | 扩展类加载器 | 应用类加载器 | 类加载的双亲委托机制 )

    文章目录 一.类加载器 二.类加载的双亲委托机制 一.类加载器 Java 虚拟机 ClassLoader 类加载器 : Bootstrap ClassLoader : 启动类加载器 , 该 加载器由 ...

  4. 如何快速写一个违背双亲委托机制的classloader

    很多情况下,不得以必须写个classloader来满足需求.例如你一个工程里你想用相同的数据库的多个版本,自己制定了一个jar包目录,没有classloader管理等等.如果是一个遵循java已经规定 ...

  5. java 整合hadoop_Spark 如何摆脱java双亲委托机制优先从用户jar加载类?

    1. 起源 spark的类加载及参数传递过程还是很复杂的,主要是因为他运行环境太复杂了,不同的集群管理器完全不一样,即使是同一集群管理器cluster和client也不一样,再加上这块探究还是需要一定 ...

  6. 违反ClassLoader双亲委派机制三部曲第二部——Tomcat类加载机制

    转载自 违反ClassLoader双亲委派机制三部曲第二部--Tomcat类加载机制 前言: 本文是基于 ClassLoader双亲委派机制源码分析 了解过正统JDK类加载机制及其实现原理的基础上,进 ...

  7. 类加载器双亲委托机制详解

    理论了解: 关于类加载器的双亲委托机制基本上都听说过,面试时可能偶尔也会被问到,但是可能都是网上去找了一个理论性的答案临时了解了一下,并未对它到底是个什么样的机制有深入的了解,所以接下来准备深入了解它 ...

  8. axure 富文本编辑器_Java的类加载器与双亲委托机制

    目录: 类加载器 java.lang.ClassLoader类 URLClassLoader与SecureClassLoader ClassLoader常见方法源码分析 双亲委托机制 图解 源码角度分 ...

  9. jvm之类加载双亲委托机制

    岁岁金河复玉关,不辞镜里望崔山.--唐代杜甫<春望> 双亲委托机制 双亲委托机制是指在类加载器加载类时,如果一个类加载器收到了加载请求,它首先将请求委托给父类加载器,如果父类加载器仍无法找 ...

最新文章

  1. C++中模块(Dll)对外暴露接口的方式
  2. 在网页中动态的生成一个gif图片
  3. css:text-align:justify的用法
  4. ssh报错:Could not load host key:/etc/ssh/ssh_host_rsa_keyssh_host_ecdsa_keyssh_host_ed25519_key...
  5. vaadin_Vaadin和DukeScript中的Hello World
  6. poj 3678 Katu Puzzle(2-sat)
  7. python发送excel文件_Python操作Excel, 开发和调用接口,发送邮件
  8. TCP/IP详解卷1 - wireshark抓包分析
  9. windows中的服务隔离 service isolation and service SID(Virtual Account)
  10. IS-IS详解(十四)——IS-IS路由开销计算与外部路由引入
  11. java中solr的面试题_面试:----利用solr实现商品的搜索功能
  12. 收藏几款好用的网页下载工具(网页下载器)
  13. Pandas基础|列方向分组变形
  14. Android黄油计划之Choreographer原理解析
  15. halcon循环语句,条件句结构格式
  16. html page 制作,webpageHTML
  17. 当北京爷们遭遇上海男人
  18. 杭电oj(Java版)——1713 相遇周期
  19. 通信电子电路(2)---使用multisim分析电路小技巧、晶体管等效电路
  20. Arduino ESP32 基于Web服务端SD文件管理系统完善

热门文章

  1. Android之Pull解析XML
  2. educoder 使用线程锁(lock)实现线程同步_性能:Lock的锁之优化
  3. linux远程执行shell命令行,linux shell 远程执行命令--ftp
  4. org.apache.jasper.JasperException: /jsp/menu.jsp (line: 8, column: 1) Page directive
  5. 划重点了!网络推广网站在建设时期该如何进行优化?
  6. java 多线程 原子操作_线程安全之原子操作
  7. 计算机显卡敀主要性能参数,显卡性能看什么参数(新手必备的显卡性能知识全解)...
  8. java unsafe cas_Java Unsafe CAS 小试
  9. word vba高效排版范例应用_Word 排版指北丨高效律师
  10. 网上服务器租借要多少钱_台湾租借日本服装多少钱-北京和益文化传媒有限公司...