目录
- 引言
-
- [1. 虚拟机的启动](#1. 虚拟机的启动)
-
- [1.1 引导类加载器](#1.1 引导类加载器)
- [1.2 初始化步骤](#1.2 初始化步骤)
- [2. 虚拟机的执行](#2. 虚拟机的执行)
-
- [2.1 主要任务](#2.1 主要任务)
- [2.2 运行时数据区](#2.2 运行时数据区)
- [2.3 垃圾收集](#2.3 垃圾收集)
-
- [2.3.1 标记-清除算法](#2.3.1 标记-清除算法)
- [2.3.2 复制算法](#2.3.2 复制算法)
- [2.3.3 标记-整理算法](#2.3.3 标记-整理算法)
- [2.3.4 分代收集](#2.3.4 分代收集)
- [3. 虚拟机的退出](#3. 虚拟机的退出)
-
- [3.1 正常退出](#3.1 正常退出)
- [3.2 异常退出](#3.2 异常退出)
- [3.3 其他退出方式](#3.3 其他退出方式)
- [3.4 关闭钩子](#3.4 关闭钩子)
- [4. 结论](#4. 结论)
引言
Java虚拟机(JVM)是Java应用程序运行的核心,它负责加载、验证、准备、解析和初始化Java类,并执行其字节码。理解JVM的生命周期对于优化程序性能、解决内存问题以及进行故障排除至关重要。本文将深入探讨JVM的启动、执行和退出过程。
1. 虚拟机的启动
1.1 引导类加载器
Java虚拟机的启动是通过引导类加载器 (bootstrap class loader)创建一个初始类 (initial class)来完成的,这个类是由虚拟机的具体实现指定的。引导类加载器通常使用C/C++编写,嵌套在JVM内部,主要负责加载核心Java类库,如java.lang.Object
等基础类。
1.2 初始化步骤
- 配置JVM装载环境 :JVM需要找到并加载相关的动态链接库文件,例如
jvm.dll
。 - 解析虚拟机参数:处理命令行参数,例如设置堆大小等。
- 设置线程栈大小:为每个线程分配默认的栈大小。
- 执行Java main方法 :最后,JVM会找到并执行指定的主类中的
main
方法。
2. 虚拟机的执行
2.1 主要任务
一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序。当程序开始执行时,JVM才开始运行;当程序结束时,JVM也随之停止。实际上,执行所谓的Java程序时,真正执行的是一个叫做Java虚拟机的进程。
2.2 运行时数据区
JVM的运行时数据区主要包括以下几个部分:
- 堆(Heap):存储对象实例(在Java中,new出来的都是存放在堆中),是垃圾回收的主要场所。
- 方法区(Method Area):存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
- 虚拟机栈(VM Stack):每个线程拥有自己的虚拟机栈,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
- 本地方法栈(Native Method Stack):与虚拟机栈类似,但为Native方法服务。
- 程序计数器(Program Counter Register):记录当前线程所执行的字节码指令地址。
2.3 垃圾收集
JVM提供自动内存管理,即垃圾收集机制,以释放不再使用的对象所占用的内存。常见的垃圾收集算法包括标记-清除、复制、标记-整理等。常用的垃圾收集器有Serial、Parallel、CMS和G1等。
2.3.1 标记-清除算法
- 标记:遍历对象图,标记所有可达对象。
- 清除:清理未被标记的对象,释放空间。
2.3.2 复制算法
- 划分内存:将可用内存划分为两部分。
- 复制存活对象:将存活对象从一部分复制到另一部分,然后清空原部分的空间。
2.3.3 标记-整理算法
- 标记:同标记-清除算法。
- 整理:将存活对象向一端移动,然后清理边界以外的内存。
2.3.4 分代收集
- 新生代:采用复制算法,频繁地进行垃圾收集。
- 老年代:通常采用标记-整理或标记-清除算法,较少进行垃圾收集。
3. 虚拟机的退出
3.1 正常退出
- 程序正常执行结束:当程序的所有非守护线程都终止时,JVM会自然退出。
- 调用System.exit()方法 :任何线程都可以调用
System.exit()
方法来强制退出JVM。如果安全管理器允许,该方法会立即终止JVM。
3.2 异常退出
- 程序在执行过程中遇到异常或错误而异常终止:例如,抛出未捕获的异常或出现严重的内部错误。
- 由于操作系统错误而导致Java虚拟机进程终止:例如,操作系统崩溃或资源耗尽。
3.3 其他退出方式
- 调用Runtime类的halt方法 :
Runtime.halt()
方法可以立即终止JVM,不执行任何清理工作。这通常用于紧急情况下的快速退出。 - JNI Invocation API:通过JNI(Java Native Interface)规范描述的方法,可以使用JNI Invocation API来加载或卸载Java虚拟机。在这种情况下,JVM的退出由JNI调用控制。
3.4 关闭钩子
- 定义:关闭钩子是一个已经初始化但尚未启动的线程,在JVM关闭时并发无序地执行。
- 用途 :执行一些必要的清理工作,确保资源得到妥善释放。可以通过
Runtime.addShutdownHook(Thread hook)
方法注册关闭钩子。
4. 结论
JVM的生命周期涵盖了从启动到退出的全过程,其间涉及复杂的类加载、内存管理和垃圾收集机制。掌握这些知识有助于开发者编写更高效、更稳定的Java程序。同时,了解JVM内部的工作原理也能够帮助我们更好地进行性能调优和故障排查。