JVM 概述

不要必應發表於2019-09-07

1. JVM 架構

JVM 概述

2. Class Loader

2.0 反射

Java 反射機制是在執行狀態中,對於任意一個類,都能知道這個類的所有屬性與方法;對於任意一個物件,都能呼叫它的任意方法和屬性;動態獲取資訊以及呼叫物件的方法的功能稱為 Java 的反射機制。

2.1 類從編譯到執行的過程

  1. 編譯器將 xxx.java 編譯成 xxx.class 位元組碼檔案
  2. ClassLoader 將位元組碼檔案轉換成 JVM 中的 Class 物件
  3. JVM 利用 Class 物件例項化為 xxx 物件

2.2 ClassLoader 的種類

  1. BootStrapClassLoader:載入核心庫 java.* (C++ 編寫)
  2. ExtensionClassLoader:載入擴充套件庫 javax.* (Java 編寫)
  3. ApplicationClassLoader:載入程式所在目錄 (Java 編寫)

2.3 類的載入

2.3.1 類載入方式

  1. 隱式載入:new
  2. 顯式載入:forName, loadClass
    • Class.forName 得到的 class 是已經初始化完成的
    • ClassLoader.loadClass 得到的 class 是還沒有進行連線的

2.3.2 類裝載過程

JVM 概述

1. 載入
  • 通過 ClassLoader 載入 class 檔案位元組碼,生成 Class 物件
2. 連線
  • 校驗:檢查載入的 class 的正確性和安全性
  • 準備:為類變數分配儲存空間並設定變數初始值
  • 解析:JVM 將常量池內的符號引用轉換為直接引用
3. 初始化
  • 執行類變數賦值和靜態程式碼塊

3. JVM 記憶體模型

3.1 按共享和獨佔分類

JVM 概述

3.2 執行緒獨佔區域

3.2.1 程式計數器(PC 暫存器)(Program Counter Register)

  • 當前執行緒所執行的位元組碼行號指示器(邏輯)
  • 改變計數器的值來選取下一條需要執行的位元組碼指令
  • 和執行緒是一對一關係,即“執行緒私有”
  • 對 Java 方法計數,如果是 Native 方法則計數器值為 Undefined
  • 不會發生記憶體洩漏

3.2.2 Java 虛擬機器棧(Stack)

JVM 概述

棧幀

每有一個方法執行,就會產生一個新的棧幀

  • 區域性變數表:執行過程中的所有變數
  • 運算元棧:入棧、出棧、複製、交換和產生消費變數
  • 動態連結:每個棧幀都包含一個指向執行時常量池中該棧幀所屬性方法的引用,持有這個引用是為了支援方法呼叫過程中的動態連線
  • 返回地址:方法執行過程中,有兩種方式推出,1. 正常返回 2.異常退出

3.2.3 本地方法棧

3.3 共享區域

3.3.1 元空間 (MetaSpace) 與持久代 (PermGen) 的區別

  • 元空間使用本地記憶體,而持久代使用的是 JVM 的記憶體
元空間相對於持久代的優勢
  • JDK7 和之前版本中,字串常量池在持久代中,而持久代使用的是 JVM 記憶體,所以更容易發生效能問題記憶體溢位
  • 類和方法的資訊大小難以確定,給永久代的大小指定帶來困難
  • 永久代會給 GC 帶來不必要的複雜性
  • 方便 HotSpot 與其他 JVM 如 Jroket 整合

3.3.2 堆 (Heap)

  • 物件例項的分配區域
  • GC 管理的主要區域

3.4 JVM 三大效能調優引數 -Xms -Xmx -Xss 的含義

  • -Xss:規定了每個執行緒虛擬棧的大小
  • -Xms:堆的初始值
  • -Xmx:堆的最大值

3.5 記憶體分配策略的區別

  • 靜態儲存:編譯時確定每個資料目標在執行時的儲存空間需求
  • 棧式儲存:編譯時資料區不確定,執行時模組入口前確定
  • 堆式儲存:編譯時和執行時都不確定,動態分配記憶體空間

3.6 棧和堆的區別

  • 管理方式:棧自動釋放,堆需要 GC
  • 空間大小:棧比堆小
  • 碎片相關:棧產生的碎片比堆小
  • 分配方式:棧支援靜態分配和動態分配,而堆只支援靜態分配
  • 效率:棧的效率比堆高