类加载和双亲委派机制

Posted yb38156

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类加载和双亲委派机制相关的知识,希望对你有一定的参考价值。

ClassLoader是什么?

它负责将 Class 的字节码形式(本质就是一个字节数组 byte[])转换成内存形式的 Class 对象

字节码有特定的复杂的内部格式,可以来自于磁盘文件 *.class,也可以是 jar 包里的 *.class,也可以来自远程服务器提供的字节流

很多字节码加密技术就是依靠定制 ClassLoader 来实现的。先使用工具对字节码文件进行加密,运行时使用定制的 ClassLoader 先解密文件内容再加载这些解密后的字节码

每个 Class 对象的内部都有一个 classLoader 字段来标识自己是由哪个 ClassLoader 加载的

class Class<T> {
  ...
  private final ClassLoader classLoader;
  ...
}

延迟加载

JVM 运行并不是一次性加载所需要的全部类,而是按需加载,也就是延迟加载

程序在运行的过程中会逐渐遇到很多不认识的新类,这时候就会调用 ClassLoader 来加载这些类

加载完成后就会将 Class 对象存在 ClassLoader 里面,下次就不需要重新加载了

JVM有哪些类加载器?

1、启动类加载器 BootstrapClassLoader 

负责加载 JVM 运行时核心类,这些类位于 JAVA_HOME/lib/rt.jar 文件中,常用内置库 java.xxx.* 都在里面,比如 java.util.*、java.io.*、java.nio.*、java.lang.* 等等

这个 ClassLoader 比较特殊,由 C 代码实现,称之为「根加载器」

2、扩展类加载器 ExtensionClassLoader 

负责加载 JVM 扩展类,它们的 jar 包位于 JAVA_HOME/lib/ext/*.jar 中,如 swing 系列、内置的 js 引擎、xml 解析器 等等,这些库名通常以 javax 开头

3、应用程序类加载器 ApplicationClassloader(系统类加载器)

直接面向用户的加载器,加载 Classpath 环境变量里定义的路径中的 jar 包和目录。我们自己编写的代码以及使用的第三方 jar 包通常都是由它来加载

使用ClassLoader类的getSystemClassLoader()方法即可获取这个加载器

双亲委派机制

当一个类加载器收到一个类加载请求时(加载.class文件),首先会把这个任务委托给父类加载器,每个类加载器递归这个操作,

只有在父类加载器在自己的搜索范围内找不到所需指定类时,子类加载器才会尝试自己去加载

俗称:"儿子"先不干,先让"老子"干,"老子"再让"老子"干....,直到干不了,再依次返回让"儿子"干

参看ClassLoader源码

class ClassLoader {
  ...
  private final ClassLoader parent;
  ...
}

工作过程:

技术图片

 

 

1.当Application ClassLoader 收到一个类加载请求时,他首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器Extension ClassLoader去完成。  

2.当Extension ClassLoader收到一个类加载请求时,他首先也不会自己去尝试加载这个类,而是将请求委派给父类加载器Bootstrap ClassLoader去完成。  

3.如果Bootstrap ClassLoader加载失败(在<JAVA_HOME>lib中未找到所需类),就会让Extension ClassLoader尝试加载。  

4.如果Extension ClassLoader也加载失败,就会使用Application ClassLoader加载。  

5.如果Application ClassLoader也加载失败,就会使用自定义加载器去尝试加载。  

6.如果均加载失败,就会抛出ClassNotFoundException异常。

 为什么要用双亲委派机制?

1、防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍
2、保证核心.class不能被篡改。通过委托方式,不会去篡改核心.class,即使篡改也不会去加载,即使加载也不会是同一个.class对象了
不同的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。
3、如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,那系统中将会出现多个不同的Object类,程序将混乱

以上是关于类加载和双亲委派机制的主要内容,如果未能解决你的问题,请参考以下文章

JVM17_Tomcat打破双亲委派机制执行顺序底层代码原理Tomcat|JDBC破坏双亲委派机制带来的面试题

JVM笔记二双亲委派机制

jvm 双亲委派模式

图解JVM类加载机制和双亲委派模型

Java虚拟机(JVM)-- 类加载器和双亲委派机制

类加载机制-双亲委派模型