一 JVM結構及各個組件原理

###如圖:image.png

  • 類加載器

      類加載器(Class loader)負責把class文件加載進運行時數據區。
    類加載器有三種:
     1.啓動類加載器(Bootstrap), $JAVAHOME/jre/lib/rt.jar
     2.擴展類加載器(Extension), $JAVAHOME/jre/lib/ext/*.jar
     3.應用程序類加載器(AppClassLoader);
    它們遵循雙親委派機制。當一個類收到了類加載請求,會把請求委派給父類加載,每一個層次類加載器都是如此,只有當父類加載器反饋不能加載時(在它的加載路徑下沒有找到所需加載的Class),子類加載器纔會嘗試自己去加載。這樣就保證了使用不同的類加載器最終得到的都是同一對象。

  • 運行時數據空間

      由五部分組成:程序計數器、本地方法棧、棧、堆、方法區。其中堆和方法區是線程共享的,其他是線程獨享、

  • 程序計數器

      程序計數器就是一條指針,指向方法區的方法字節碼,由執行引擎(Execution Engine)讀取下一條指令。執行引擎負責解釋命令,提交操作系統執行。

  • 本地方法棧

      本地方法棧(Native method stack)會調用本地接口(Native Interface)實現線程的創建。

  • 棧內存

      棧主管Java程序的運行,在線程創建時創建,生命期是跟隨線程的生命期,線程結束棧內存也就釋放。
    棧主要保存三類數據:
     1.本地變量(Local Variables): 輸入參數和輸出參數以及方法內的變量(8種基本數據類型+對象的引用變量)
     2.棧操作(Operand Stack): 記錄出棧、入棧的操作
     3.棧幀數據(Frame Data): 包括類文件、實例方法等
    棧運行遵循“先進後出”原則。
    棧的大小和具體JVM的實現有關,通常在256K~756K之間。
    常見異常:
    java.lang.StackOverflowError
     (1)棧的小格子不夠了,不是因爲內存溢出!
     (2)調用了太多的方法,導致棧溢出。比如死循環遞歸調用。

  • 堆內存

      堆存儲對象的實例。堆分爲新生代和老年代。Hot Spot JVM把年輕代分爲了三部分,一個Eden和兩個survivor(From和To),默認是8:1:1。Survivor 區相當於是 Eden 區和 Old 區的一個緩衝,設置兩個 Survivor 區最大的好處就是解決內存碎片化。
    常見異常:
    java.lang.OutOfMemoryError: Java heap space
     (1)Java虛擬機的堆內存設置不夠,可以通過參數-Xms、-Xmx來調整。
     (2)代碼中創建了大量大對象,並且長時間不能被垃圾收集器收集。

  • 方法區

      存儲靜態變量、常量、類結構(構造方法/接口定義)、運行時常量池。
    運行時常量池:虛擬機會將各個class文件中的常量池載入到運行時常量池中,即編譯期間生成的字面量、符號引用,總之就是裝載class文件。
    方法區是Java虛擬機規範中的定義,是一種規範。
    對於Java8,元空間(MateSpace)是方法區的實現,元空間並不在虛擬機中而是使用本機物理內存。
    但靜態變量和常量池並不存入元空間,而是存儲在堆中。
    字符串常量池也儲存在堆中。

棧、堆、方法區的交互關係

  棧中的引用對象指向堆內存中對象的實例數據,堆內存實例數據是根據方法區類結構產生。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章