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);

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影片中學習的筆記,均經過實踐,加上自己的理解。地址://www.bilibili.com/video/BV1PJ411n7xZ ,強烈推薦!!!

【作者簡介】:
秦懷,公眾號【秦懷雜貨店】作者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。這個世界希望一切都很快,更快,但是我希望自己能走好每一步,寫好每一篇文章,期待和你們一起交流。

Tags: