《Java 虚拟机原理》7.1 精选 —— 总览
1.一个程序在 JVM 中运行的完整流程
java程序执行流程.JPG说明:
① 类加载器把字节码加载到方法区
② 方法区的字节码被 JVM new,在堆内存中生成字节码对象
③ 字节码对象被 GC 的要求有:该类没有在其他任何地方被引用;该类的所有的实例对象都已被 GC;该类的类加载器的实例已被 GC
2.Java 虚拟机的生命周期
JVM 的生命周期可以分为启动、运行、退出。
(1) 启动
JVM 的启动过程是类加载,通过类加载器把二进制字节码加载到 JVM。
类加载器采用双亲委派模型, 其类型有 3 种:
① Bootstrap ClassLoader 启动类加载器:负责加载系统类和 /lib 目录的 jar 和类,例如 String
② ExtClassLoader 扩展类加载器:负责加载 /lib/ext 目录下的 jar 和类
③ AppClassLoader 应用程序类加载器:负责加载当前应用 ClassPath 的 jar 和类
④ UserDefinedClassLoader 用户自定义加载器:负责加载用户自定义的 jar 和类
示例如下,执行 main 方法,需要加载 Test01。根据双亲委派模型即向上检查、向下加载,JVM 从 AppClassLoader、ExtClassLoader 到 Bootstrap ClassLoader 检查和加载 Test01。Test01 是用户自定义类,Test01 没有指定父类即默认父类是 Object 类,被
AppClassLoader 加载。
public class Test01 {
public static void main(String[] args) {
System.out.println("123");
}
}
类的生命周期:
① 加载:通过全类名获取该类的二进制字节流、将字节流所代表的静态存储结构转换为方法区的运行时数据结构、在内存中生成一个代表该类的 Class 对象(方法区数据的访问入口);
② 验证:验证文件格式、字节码验证、魔数验证
③ 准备:分配内存给类变量,并设置类变量初始值。如果是基本数据类型,就会给他们设置默认值;
④ 解析:将常量池内的符号引用替换为直接引用
⑤ 初始化:new 指令、getstatic 指令、putstatic 指令、invokestatic 指令、 java.lang.reflect 的反射等
⑥ 使用:用户程序使用
⑦ 卸载:该类的所有的实例对象都已被GC、该类没有在其他任何地方被引用、该类的类加载器的实例已被GC
(2) 运行
一个JVM 进程的运行,实际上是 Java 程序的运行。当程序运行结束后,JVM 进程也就结束。
JVM 的守护线程:
Java 有 2 种进程,User Thread 用户线程、Daemon Thread 守护线程。例如,用户线程是指用户自定义的 main 函数,而守护线程是服务于用户线程的,例如 GC 垃圾回收线程。两种线程的生命周期是一致的,前者优先级高于后者的。
(3)退出
JVM 的退出有多种场景,如下所示。
① 程序正常结束运行
② 程序中调用 System.exit() 等方法
③ 程序运行过程中,遇到异常错误终止
④ 操作系统、硬件原因导致 JVM 进程被结束
3.Java 程序运行的案例
image.pngjdk1.7 及以下是方法区,jdk1.8 是元空间 Metaspace