【深入理解JVM】JVM的內存結構(堆、棧、GC)


  最近一直在看JVM相關的東西,在這裏整理一下,方便以後覆盤,有錯誤的地方歡迎留言。

Java跨平臺

  不同操作系統使用的指令不同,JVM 可以將字節碼翻譯成特定平臺下的機器碼運行,在不同平臺安裝對應的 JVM,就可以運行字節碼,通過 JVM 這一“中間層”屏蔽了操作系統的差異,不同 JDK 適應不同的操作系統,使Java具有跨平臺的特性。

什麼是JVM?

   JVM 即 Java Virtual Machine(Java虛擬機) , 模擬一個計算機來達到計算機所具有的計算功能。屏蔽各計算機硬件和軟件之間的差異,使字節碼文件可以“到處運行”。

JVM的組成

JVM由四部分組成:

  • 類加載器
  • 運行時數據區
  • 執行引擎
  • 本地接口

運行時數據區

   由 堆、棧、程序計數器、本地方法棧、方法區 五部分組成。
在這裏插入圖片描述
在這裏插入圖片描述由線程共享
在這裏插入圖片描述由線程獨有,每個線程都包含 棧、程序計數器、本地方法棧。

在這裏插入圖片描述
線程中每執行一個方法,棧中進入一個棧幀,棧幀由四部分組成。

  • 局部變量表
  • 操作數棧
  • 動態鏈接
  • 方法出口
public class Test{
    public static void main(String[] args){
         int i = 1;
         int j = 2;
         int k = i + j;
         System.out.println(k);
    }
}

由Test.java說明程序運行時棧中情況。
javac Test.java 編譯成Test.class。
javap -c Test.class>Test.txt 將字節碼反編譯結果輸出到Test.txt文件中,內容如下:

Compiled from “Test.java”
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object.""😦)V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: istore_3
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_3
12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
15: return
}

可以去下列網址查看 iconst_1 JVM字節碼指令的含義
https://www.cnblogs.com/tenghoo/p/jvm_opcodejvm.html

大致意思:
  把1放入操作數棧,將1賦給變量 i 存入局部變量,j 同理,將1和2相加爲3再賦給變量k。

  程序計數器會記錄將要執行的指令行號,這樣在掛起後恢復等操作時就可以知道上次執行的位置。

棧幀中的動態鏈接

這就要說一下靜態鏈接,在類加載過程中包含如下步驟:
在這裏插入圖片描述
  靜態鏈接在類加載過程中的解析階段進行,將部分符號引用轉爲直接引用,字節碼符號無法直接使用,直接引用類似於地址,這樣纔可以使用。

  動態鏈接是在運行時將符號引用轉爲直接引用。
  方法出口可以理解爲方法的 return。

本地方法棧

  在Java之前使用C的很多,Java有些也是用C實現的,Java中也有 native修飾的方法,這樣的方法就是用C實現的,這些字符存在本地方法棧中,執行引擎會找C語言的函數庫(.dll)。

執行引擎

執行引擎執行字節碼的方式:

  • 解釋執行:一行一行邊翻譯邊執行
  • JIT即時編譯執行:這裏有熱點代碼的概念,被多次調用的方法或被多次執行的循環體視爲熱點代碼,熱點代碼會被編譯執行,這樣效率高點

堆和Full GC

在這裏插入圖片描述
堆 由年輕代、老年代組成。在JVM啓動時創建,是GC垃圾回收的主要對象,也是分配存儲區最大的一塊。
年輕代 由Eden區(伊甸區)、From Survivor、To Survivor組成。

這裏需要說一下輕GC(Minor gc)和Full GC。

  • 新創建的對象需要放入Eden區,當Eden區滿後,GC回收沒有被引用的對象,剩餘對象放到From Survivor區;
  • 當From Survivor區滿後,清空From Survivor區,未被回收的對象放入To Survivor區;
  • 此時From和To身份互換,From變爲To,To變爲From,如此循環15次(默認15次),當To區滿時,將未被清理的對象放入老年代;
  • 當老年代滿時,觸發Full GC(之前都是Minor GC),由於不同的垃圾回收器機制不同,可能把之前的區都清理,也可能只清理老年區(涉及到垃圾回收器和算法,以後再寫一篇補上)。

堆、棧、方法區的愛恨糾葛

在這裏插入圖片描述
   s 學生變量存在棧中,在堆中創建對象,將對象的地址賦給s變量;
堆中的對象實例指向方法區的類模板,通過類模板創建實例對象。

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