类的加载器及加载过程
文章目录
类的加载过程
加载—>验证—>准备—>解析—>初始化
加载:
- 通过一个类的全限定类名获取此类的二进制字节流
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
- 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
链接(验证、准备、解析):
- 验证:确保Class文件的字节流包含信息符合当前虚拟机要求;保证加载类的正确性,不会危害虚拟机的自身安全;
- 准备:为变量分配默认值(不包括final修饰的);不会为实例变量分配初始化;
- 解析:将常量池中的符号引用转换为直接引用的过程;
初始化:
任何一个类声明以后,内部至少存在一个类的构造器。
初始化阶段就是执行类构造器方法()的过程
类加载器的分类
引导类加载器:BootstrapClassLoader 启动类加载器( C/C++实现,嵌套在JVM内部)
- java的核心类库都是使用引导类加载器进行加载。
- 加载扩展类和系统类加载器,并指定为他们的父类加载器。
自定义类加载器(所有派生于抽象类ClassLoader的类加载器)
- 扩展类加载器: ExtentionClassLoader
- 派生于ClassLoader类
- 父类加载器为启动类加载器
- 主要加载核心类库之外的扩展类
- 系统类加载器(应用程序加载器):AppClassLoader
- 派生于ClassLoader类
- 父类加载器为扩展类加载器
- 加载环境变量指定下的类库
- 对用户自定义类来说:默认使用系统类加载器进行加载
获取ClassLoader的途径
- 获得当前类:Class.forName(“java.lang.String”).getClassLoader()
- 获得当前线程上下文:Thread.currentThread().getContextClassLoader()
- 获得系统:ClassLoader.getSystemClassLoader()
双亲委派机制(重点)
-
Java虚拟机对class文件采用按需加载的方式
-
加载某个类的class文件时,java虚拟机采用的是双亲委派模式
-
工作原理:
- 如果一个类加载器收到类加载的请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行;
- 如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终到达顶层的启动类加载器;
- 如果父类加载器可以完成类加载任务,就成功返回,否则子类尝试自己去加载;
-
优势:
- 避免类的重复加载
- 保护程序安全,防止核心API被随意篡改(沙箱安全机制)
判断两个Class对象是否为同一个类
- 全路径类名相同(即包括包名)
- 加载这个类的ClassLoader(指ClassLoader实例对象)必须相同