深入理解JVM(一):类的生命周期
github地址:
https://github.com/lishanglei/jvm_study.git
类的生命周期
在java代码中,类的加载,连接,初始化过程都是在程序运行期间完成的
在如下几种情况,java虚拟机将会结束自己的生命周期
- 执行System.exit()方法
- 程序正常执行结束
- 程序在执行过程中遇到了异常或错误而导致异常终止
- 由于操作系统出现错误而导致虚拟机进程终止
-
加载:
- 通过一个类的全限定名来获取此类的二进制字节流
- 将这个字节流所代表的静态存储接口转化为方法区的运行时数据结构
- 在内存中生成一个代表这个类的java.lang.Class对象,作为存放这个类的各种数据访问的入口(规范并未说明Class对象位于哪里,HotSpot虚拟机将其放在了方法区中)
加载.class文件的方式:
- 从本地系统中直接加载
- 通过网络下载.class文件
- 从zip,jar等归档文件中加载.class文件
- 从专有数据库中提取.class文件
- 将java源文件动态编译为.class文件(动态代理,jsp等)
-
验证
- 文件格式校验
- 元数据校验
- 字节码校验
- 符号引用校验
- 取消校验: -Xverify:none
-
准备
- 为类的静态变量分配内存并设置初始值,这些变量存储于方法区中
- 如果类的静态变量是被final修饰的,会直接赋值
-
解析
- 将常量池中的符号引用转为直接引用,在字节码文件中,类,接口,字段,方法等类型都是由一组符号来表示,其形式由java虚拟机规范中的Class文件格式定义.在虚拟机执行特定指令之前,需要将符号引用转为目标的指针,相对偏移量或者句柄,.这样可以通过此类直接引用在内存中定位调用的具体位置
-
初始化
- 为类的静态变量赋予正确的初始值,初始化阶段是执行类构造器cInit()方法的过程,类构造器方法是由编译器自动收集类中所有类变量的赋值动作和static静态代码块中的语句合并产生,编译器收集的顺序由语句在源文件中出现的顺序决定.静态代码块中只能访问到定义在静态代码块之前的变量,定义在静态语句块之后的变量,在静态代码块中只可以赋值,不能访问