三.虚拟机执行子系统
3.1 类文件结构
3.2 虚拟机类加载机制
3.2.1 类的生命周期
加载->验证->准备->解析->初始化->使用->卸载
- 加载:是“类加载”过程的一个阶段,完成3件事,(1)通过全限定名获取二进制字节流(2)将这个字节流代表的静态存储结构转化为方法区的运行时存储结构(3)在内存中生成代表这个类的对象,作为方法区这个类的各种数据的访问入口
- 验证:主要完成4个阶段的验证动作,文件格式、元数据验证、字节码验证、符号引用验证。
- 准备:正式为“类变量”即静态变量分配内存并设置初始值。
- 解析:虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用,以一组符号来描述引用的目标,符号可以只任何形式的字面量。直接引用,直接引用可以只直接指向目标的指针、相对偏移量或能间接定位到目标的句柄。
- 初始化:类加载过程的最后一步,根据程序员通过程序制定的主观计划去初始化类变量和其他资源。
3.2.2 类加载器
用于实现类的加载动作(生命周期的第一步),但它的作用不止于此,在jdk有一个抽象类,ClassLoader,通过重写loadClass()方法自定义类加载器。注意,用不同类加载器去加载同一个类,比较两个类时为 false。OSGI架构具有独特的类加载架构。
在虚拟机角度来讲只有两种不同的类加载器,(1)种是启动类加载器(Bootstrap ClassLoader),由C++实现,是虚拟机的一部分,(2)所有其他类加载器,由java语言实现,独立于虚拟机外部,全部继承自ClassLoader。
而在jdk中可以划分的更加细致一些,主要使用系统提供的以下3种:
- 启动类加载器(Bootstrap ClassLoader),主要负责加载<JAVA_HOME>\lib目录中的类
- 扩展类加载器(Extension ClassLoader),由sun.misc.Launcher$ExtClaaLoader实现,负责加载<JAVA_HOME>\lib\ext目录中的类,或被java.ext.dirs 系统变量指定的路径的类库。
- 应用程序类加载器(Application ClassLoader),由sun.misc.Launcher$App-ClaaLoader实现,它也是系统类加载器,是getSystemClassLoader()方法的返回值,主要负责加载用户路径(ClassPath)中国指定的类库。
双亲委派模型:箭头应该是向上的,这种类加载器之间的父子关系不是以继承关系实现的,而是以组合关系实现,复用父加载器代码。
工作过程:如果一个类收到类加载请求,首先它不会自己去尝试加载这个类,而是把请求委派给父加载器去完成,每一层都是如此。因此最总都交给了启动类加载器,只有启动类加载器无法完成时,子类才会自己尝试加载。
优点:使类同类加载器一起具备了一种带有优先级的层次关系。保证同一个类由不同类加载器加载时,最终都是使用同一个类加载器去加载,即保证了一致性。
graph TD
A[启动类加载器] -->B[扩展类加载]
B --> C[应用程序类加载器]
C --> D[自定义类加载器 ]
C --> E[自定义类加载器]
箭头应该是向上的