JVM笔记 -- JVM的生命周期介绍

Github仓库地址:https://github.com/Damaer/JvmNote
文档地址:https://damaer.github.io/JvmNote/

JVM生命周期

  • 启动
  • 执行
  • 退出

启动

Java虚拟机的启动时通过引导加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由Java虚拟机的具体实现指定的。

自定义的类是由系统类加载器加载的。自定义类的顶级父类都是ObjectObject作为核心api中的类,是需要被引导加载器(bootstrap class loader)加载的。父类的加载是优先于子类加载的,所以要加载自定义的之前,会就加载Object类。

执行

  • Java虚拟机执行的时候有一个清晰的任务:执行Java程序。
  • 真正执行程序的是一个叫Java虚拟机的进程。

退出

虚拟机的退出有以下几种情况:

  • 程序正常执行结束
  • 程序执行过程中遇到了异常或者错误而异常终止
  • 由于操作系统出现错误而导致Java虚拟机进程终止
  • 某线程调用Runtime类或者System类的exit方法,或者Runtime类的halt()方法,并且Java安全管理器也允许这次操作的条件下。
  • JNIjava native Interface):用JNIapi加载或者卸载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); }

Runtimeexit()方法,里面调用的是Shutdown.exit(status)

public void exit(int status) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkExit(status); } Shutdown.exit(status); }

我们看Shutdownexit()方法,当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);

image-20201222221827719

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 ,强烈推荐!!!

【作者简介】
秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使缓慢,驰而不息。这个世界希望一切都很快,更快,但是我希望自己能走好每一步,写好每一篇文章,期待和你们一起交流。


__EOF__

本文作者秦怀杂货店
本文链接https://www.cnblogs.com/Damaer/p/14504690.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   第十六封  阅读(140)  评论(0编辑  收藏  举报
编辑推荐:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示