简单的梳理JVM(二)——JVM类加载机制
目录
一、类的加载器
先看下图:
四种类加载器介绍
Bootstrap ClassLoader
- 负责加载$JAVA_HOME中 jre/lib/rt.jar里所有的class或Xbootclassoath选项指定的jar包。由C++实现,不是ClassLoader子类。
Extension ClassLoader
- 负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar 或-Djava.ext.dirs指定目录下的jar包。
App ClassLoader
- 负责加载classpath中指定的jar包及 Djava.class.path 所指定目录下的类和jar包。
Custom ClassLoader
- 通过java.lang.ClassLoader的子类自定义加载class,属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader。
加载流程简述
加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载,就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。
二、JVM类加载机制
1.全盘负责、父类委托、缓存机制
全盘负责
- 当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入
父类委托
- 先让父类加载器试图加载该类,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类
缓存机制
- 缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区寻找该Class,只有缓存区不存在,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓存区。这就是为什么修改了Class后,必须重启JVM,程序的修改才会生效
2.双亲委派模型
2.1 工作流程
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。
- 当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。
- ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。
- 如果 BootStrapClassLoader加载失败(例如在 $JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;
- 若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果 AppClassLoader也加载失败,则会报出异常ClassNotFoundException
2.2 双亲委派模型意义
- 系统类防止内存中出现多份同样的字节码
- 保证Java程序安全稳定运行
总结
本章主要介绍:
- 四种类加载器简单介绍
- 类加载机制的三种方式
- 双亲委派模型的流程