以下文档约定:
1、每个 Class文件
都有代表着Java语言中的一个 类
或 接口
的可能
2、 Class文件
也并非特指某个存在于具体磁盘中的文件,而应当是 一串二进制字节流
,无论其以何种形式存在,包括但不限于磁盘文件、网络、数据库、内存或者动态产生等。
-----------------------------------------------------------------------------读书笔记摘自 书名:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)作者:周志明
与那些在编译时需要进行连接的语言不同,在Java语言里面,类型的加载、连接和初始化过程都是在 程序运行期间
完成的。
虚拟机的类加载机制
Java虚拟机把描述类的数据从 Class文件
加载到内存
,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型
,这个过程被称作 虚拟机的类加载机制。
类加载器(Class Loader)
Java虚拟机设计团队有意把类加载阶段中的 “通过一个类的全限定名来获取描述该类的二进制字节流
” 这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需的类。实现这个动作的代码
被称为“类加载器”(Class Loader)。
-----------------------------------------------------------------------------读书笔记摘自 书名:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)作者:周志明
类加载器双亲委派模型机制?
当一个类收到了类加载请求时,不会自己先去加载这个类,而是将其委派给父类,由父类去加载,如果此时父类不能加载,反馈给子类,由子类去完成类的加载。
类加载器有哪些?
两种不同的类加载器:
一种是启动类加载器
(BootstrapClassLoader),这个类加载器使用C++语言实现,是虚拟机自身的一部分;
1、启动类加载器
另外一种就是其他所有的类加载器
,这些类加载器都由Java语言实现,独立存在于虚拟机外部,并且全都继承自抽象类java.lang.ClassLoader
。
1、扩展类加载器
2、应用程序类加载器
3、自定义的类加载器
类生命周期
类从被加载到虚拟机内存
中开始,到卸载出内存
为止,它的整个生命周期。
加载
、验证
、准备
、初始化
和卸载
这五个阶段的顺序是确定的,而解析
阶段则不一定:它在某些情况下可以在初始化阶段之后再开始。
-----------------------------------------------------------------------------读书笔记摘自 书名:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)作者:周志明
类加载时机
什么情况加载
《Java虚拟机规范》未强制约束,由虚拟机实现自由把握
。 但是严格规定了 有且只有
六种情况必须立即对类进行 “初始化
”:类什么时候执行初始化
类加载(Class Loading)过程
加载
、验证
、准备
、解析
、初始化
1.加载(Loading)
在加载阶段,虚拟机需要完成以下三件事情:
1、通过一个类的全限定名来获取定义此类的 二进制字节流
。(没有指明要从哪里获取、如何获取。(这里给了开发很大的创作空间))
2、将这个字节流所代表的 静态存储结构 转化为方法区
的 运行时数据结构。
3、在Java堆
中生成一个代表这个类的 java.lang.Class对象
,作为方法区这些数据的访问入口。
注意
1、加载阶段结束后,Java虚拟机外部的二进制字节流
就按照虚拟机所设定的格式存储在方法区之中了,方法区中的数据存储格式完全由虚拟机实现自行定义,《Java虚拟机规范》未规定此区域的具体数据结构。
2、非数组类型的加载阶段是加载阶段中获取类的二进制字节流的动作, 数组类本身不通过类加载器创建,它是由Java虚拟机直接在内存中动态构造出来的。数组类的元素类型(Element Type,指的是数组去掉所有维度的类型)还是要靠类加载器来完成加载。
2.验证:
目的是确保Class文件
的字节流
中包含的信息符合《Java虚拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。
验证阶段大致上会完成下面四个阶段的检验动作:
文件格式
验证、元数据
验证、字节码
验证、符号引用
验证。
3.准备:
准备阶段是正式为类 静态变量
(即被static修饰的变量)分配内存
并 设置初始值
的阶段。
“通常情况” 下是数据类型的零值
假设一个类变量的定义为:
public static int value = 123;
那变量 value 在准备阶段过后的初始值为0
而不是123
;
“特殊情况”
假设上面类变量value的定义修改为:
public static final int value = 123;
那变量 value 在准备阶段过后的初始值为123
;
注意:
1、类变量在方法区
就完全是一种对逻辑概念的表述。JDK 7及之前,HotSpot使用永久代
来实现方法区;JDK 7及之后,类变量
则会随着Class对象
一起存放在Java堆
中
2、 这时候进行内存分配的 仅包括类变量,而不包括实例变量, 实例变量将会在对象实例化时随着对象一起分配在Java堆中;
4.解析:
解析阶段是Java虚拟机将 常量池 内的 符号引用 替换为 直接引用 的过程。
解析动作主要针对
类或接口
、字段
、类方法
、接口方法
、方法类型
、方法句柄
和调用点限定符
这7类符号引用进行。
符号引用(Symbolic References) :以
一组符号
来描述所引用的目标,符号可以是任何形式的字面量
,只要使用时能无歧义地定位到目标即可。
直接引用(Direct References) :是可以直接指向目标的指针
、相对偏移量
或者是一个能间接定位到目标的句柄
。
5.初始化
类的初始化阶段是类加载过程的最后一个步骤,之前介绍的几个类加载的动作里,除了在加载阶段用户应用程序可以通过自定义类加载器的方式局部参与外,其余动作都完全由Java虚拟机来主导控制。直到初始化阶段,Java虚拟机才真正开始执行类中编写的Java程序代码,将主导权移交给应用程序。
进行准备阶段时,变量已经赋过一次系统要求的初始零值
,而在初始化阶段,则会根据程序员通过程序编码制定的主观计划去初始化类变量
和其他资源
。我们也可以从另外一种更直接的形式来表达:初始化阶段就是执行类构造器<clinit>()方法的过程
。
参考:类构造器<clinit>(),实例构造器< init>() 学习笔记
-----------------------------------------------------------------------------读书笔记摘自 书名:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)作者:周志明