JVM笔记 -- JVM的生命周期介绍
Github仓库地址:https://github.com/Damaer/JvmNote
文档地址:https://damaer.github.io/JvmNote/
JVM生命周期
- 启动
- 执行
- 退出
启动
Java虚拟机的启动时通过引导加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由Java虚拟机的具体实现指定的。
自定义的类是由系统类加载器加载的。自定义类的顶级父类都是Object,Object作为核心api中的类,是需要被引导加载器(bootstrap class loader)加载的。父类的加载是优先于子类加载的,所以要加载自定义的之前,会就加载Object类。
执行
Java虚拟机执行的时候有一个清晰的任务:执行Java程序。- 真正执行程序的是一个叫
Java虚拟机的进程。
退出
虚拟机的退出有以下几种情况:
- 程序正常执行结束
- 程序执行过程中遇到了异常或者错误而异常终止
- 由于操作系统出现错误而导致Java虚拟机进程终止
- 某线程调用
Runtime类或者System类的exit方法,或者Runtime类的halt()方法,并且Java安全管理器也允许这次操作的条件下。 JNI(java native Interface):用JNI的api加载或者卸载Java虚拟机的时候,Java虚拟机可能异常退出。
System.exit()和Runtime.halt()
下面分析System.exit()和Runtime.halt():
System.exit()其实调用的是Runtime对象的exit()方法,Runtime.getRuntime()获取的是当前的运行时状态,也就是Runtime对象。
public static void exit(int status) {
Runtime.getRuntime().exit(status);
} 看Runtime的exit()方法,里面调用的是Shutdown.exit(status)。
public void exit(int status) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkExit(status);
}
Shutdown.exit(status);
} 我们看Shutdown的exit()方法,当status不为0的时候,调用的是halt(status)。
static void exit(int status) {
boolean runMoreFinalizers = false;
synchronized (lock) {
if (status != 0) runFinalizersOnExit = false;
switch (state) {
case RUNNING: /* Initiate shutdown */
state = HOOKS;
break;
case HOOKS: /* Stall and halt */
break;
case FINALIZERS:
if (status != 0) {
/* Halt immediately on nonzero status */
halt(status);
} else {
/* Compatibility with old behavior:
* Run more finalizers and then halt
*/
runMoreFinalizers = runFinalizersOnExit;
}
break;
}
}
if (runMoreFinalizers) {
runAllFinalizers();
halt(status);
}
synchronized (Shutdown.class) {
/* Synchronize on the class object, causing any other thread
* that attempts to initiate shutdown to stall indefinitely
*/
sequence();
halt(status);
}
} 而halt(int status)本质上调用的是一个本地方法halt0(int status),暂停虚拟机进程,退出。
static void halt(int status) {
synchronized (haltLock) {
halt0(status);
}
}
static native void halt0(int status); 
Runtime是运行时数据的对象,全局单例的,可以理解为它代表了运行时数据区。是一个饿汉式单例模式。从 JDK1.0 开始就,可以看出,这就是虚拟机的核心类!

下面可以测试一下Runtime的属性:
public class RuntimeTest {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println(runtime.getClass().getName());
System.out.println("maxMemory: "+runtime.maxMemory()/1024/1024);
System.out.println("totalMemory: "+runtime.totalMemory()/1024/1024);
System.out.println("freeMemory: "+runtime.freeMemory()/1024/1024);
}
} 运行结果:表示最大的内存是2713M,总的内存是184M,可以使用内存是180M。
java.lang.Runtime maxMemory: 2713 totalMemory: 184 freeMemory: 180
PS:本笔记是在宋红康老师的JVM视频中学习的笔记,均经过实践,加上自己的理解。地址:https://www.bilibili.com/video/BV1PJ411n7xZ ,强烈推荐!!!
【作者简介】:
秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使缓慢,驰而不息。这个世界希望一切都很快,更快,但是我希望自己能走好每一步,写好每一篇文章,期待和你们一起交流。
记录以及分享自己的技术,专注于Java~
360集团公司氛围 381人发布
