JVM筆記 -- JVM的生命周期介紹
Github倉庫地址://github.com/Damaer/JvmNote
文檔地址://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影片中學習的筆記,均經過實踐,加上自己的理解。地址://www.bilibili.com/video/BV1PJ411n7xZ ,強烈推薦!!!
【作者簡介】:
秦懷,公眾號【秦懷雜貨店】作者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。這個世界希望一切都很快,更快,但是我希望自己能走好每一步,寫好每一篇文章,期待和你們一起交流。

