JVM 面試知識整理

wangjie201701發表於2018-05-19

JVM 知識整理

  1. JVM 類載入機制
  • 載入(將檔案載入到記憶體中)
  • 驗證(確保class檔案的位元組流中包含的資訊符合當前虛擬機器的要求,並且不會危害虛擬機器自身的安全)
  • 準備 (準備階段是正式為類變數分配記憶體並設定類變數的初始值階段,即在方法區中分配這些變數所使用的記憶體空間)
  • 解析 (解析階段是指虛擬機器將常量池中的符號引用替換為直接引用的過程。)
  • 初始化 (開始真正執行類中定義的Java程式程式碼)
  1. JVM提供了3種類載入器

    • 啟動類載入器Bootstrap ClassLoader(負責載入 JAVA_HOME\lib rt.jar)
    • 擴充套件類載入器Extension ClassLoader(負責載入 JAVA_HOME\lib\ext)
    • 應用程式類載入器ApplicationClassLoader(負責載入使用者路徑(classpath)上的類庫)
  2. JVM 通過雙親委任模型進行類的載入。

    • 當一個類載入器收到類載入任務,會先交給其父類載入器去完成,因此最終載入任務都會傳遞到頂層的啟動類載入器,只有當父類載入器無法完成載入任務時,才會嘗試執行載入任務。
    • 採用雙親委派的一個好處是比如載入位於rt.jar包中的類java.lang.Object,不管是哪個載入器載入這個類,最終都是委託給頂層的啟動類載入器進行載入,這樣就保證了使用不同的類載入器最終得到的都是同樣一個Object物件。
  3. 類例項化順序,比如父類靜態資料,建構函式,欄位,子類靜態資料,建構函式,欄位他們的執行順序

    • 先靜態、先父後子
    • 先靜態:父靜態 > 子靜態
    • 優先順序: 父類 > 子類靜態程式碼塊 > 非靜態程式碼塊 > 建構函式
    • 一個類的例項化過程:
      • (1)父類中的static 程式碼塊,當前類的static
      • (2)順序執行父類的普通程式碼塊
      • (3)父類的建構函式
      • (4)子類普通程式碼塊
      • (5)子類(當前類)的建構函式,按順序執行。
      • (6)子類方法的執行。
  4. JVM記憶體分配

    • 根據JVM規範,JVM 記憶體共分為虛擬機器棧、堆、方法區、程式計數器、本地方法棧五部分組成。
    • 其中 堆 、方法區由所有執行緒共享的資料區
    • 虛擬機器棧 、程式計數器、本地方法棧 為執行緒隔離資料區
    虛擬機器棧 執行緒建立時產生,方法執行時生成棧幀
    本地方法棧
    方法區 儲存類的後設資料資訊 常量等
    java程式碼中所有的new操作
    非堆 JVM自用的區域,方法區、JVM內部處理、類方法,構造方法等
  5. java 8 的記憶體分代改進 從永久代到元空間,在小範圍自動擴充套件永生代避免溢位。

  6. JVM 垃圾回收機制,何時出發MinorGC等操作

    • 垃圾回收機制:不同的物件生命週期不同。
    • JVM 中共劃分為三個代:年輕代、老年代和持久代。
    • 年輕代:存放所有新生代的物件;
    • 老年代:在年輕代經歷了N次垃圾回收仍然存活的物件,將被放到老年代中,故都是一些生命週期較長的物件;
    • 持久代:用於存放靜態檔案,如java類、方法等。
    • 新生代的垃圾收集器名為"minor gc",老生代的GC命名為"Full Gc 或者 Major GC",其中System.gc()強制執行的Full Gc
  • 判斷物件是否需要回收的方法有兩種:
    • 1 引用計數 :當某物件的引用數為0時,便可以進行垃圾收集。
    • 2 物件引用遍歷 :如果某物件不能從這些根物件的一個(至少一個)到達,則將它作為垃圾收集。
  • 觸發GC的條件:
    • 1 GC在優先順序最低的執行緒中執行,一般在引用程式空閒即沒有應用執行緒在執行時被呼叫。
    • 2 Java 堆記憶體不足時,GC被呼叫。
  • GC 演算法 GC最基礎的演算法有三種:標記-清除演算法、複製演算法、標記壓縮演算法,我們常見的垃圾回收器一般都採用分代收集演算法
    • 標記 -清除演算法,“標記-清除”(Mark-Sweep)演算法,如它的名字一樣,演算法分為“標記”和“清除”兩個階段:首先標記出所有需要回收的物件,在標記完成後統一回收掉所有被標記的物件。
    • 複製演算法,“複製”(Copying)的收集演算法,它將可用記憶體按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當這一塊的記憶體用完了,就將還存活著的物件複製到另外一塊上面,然後再把已使用過的記憶體空間一次清理掉。
    • 標記-壓縮演算法,標記過程仍然與“標記-清除”演算法一樣,但後續步驟不是直接對可回收物件進行清理,而是讓所有存活的物件都向一端移動,然後直接清理掉端邊界以外的記憶體
    • 分代收集演算法,“分代收集”(Generational Collection)演算法,把Java堆分為新生代和老年代,這樣就可以根據各個年代的特點採用最適當的收集演算法。
  • 垃圾回收器
    • Serial收集器,序列收集器是最古老,最穩定以及效率高的收集器,可能會產生較長的停頓,只使用一個執行緒去回收。
    • ParNew收集器,ParNew收集器其實就是Serial收集器的多執行緒版本。
    • Parallel收集器,Parallel Scavenge收集器類似ParNew收集器,Parallel收集器更關注系統的吞吐量。
    • Parallel Old 收集器,Parallel Old是Parallel Scavenge收集器的老年代版本,使用多執行緒和“標記-整理”演算法
    • CMS收集器,CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。
    • G1收集器,G1 (Garbage-First)是一款面向伺服器的垃圾收集器,主要針對配備多顆處理器及大容量記憶體的機器. 以極高概率滿足GC停頓時間要求的同時,還具備高吞吐量效能特徵
  1. GC分析 命令調優
    • GC日誌分析
   2016-07-05T10:43:18.093+0800: 25.395: [GC [PSYoungGen: 274931K->10738K(274944K)] 371093K->147186K(450048K), 0.0668480 secs] [Times: user=0.17 sys=0.08, real=0.07 secs] 
2016-07-05T10:43:18.160+0800: 25.462: [Full GC [PSYoungGen: 10738K->0K(274944K)] [ParOldGen: 136447K->140379K(302592K)] 147186K->140379K(577536K) [PSPermGen: 85411K->85376K(171008K)], 0.6763541 secs] [Times: user=1.75 sys=0.02, real=0.68 secs]
複製程式碼

通過上面日誌分析得出,PSYoungGen、ParOldGen、PSPermGen屬於Parallel收集器。其中PSYoungGen表示gc回收前後年輕代的記憶體變化;ParOldGen表示gc回收前後老年代的記憶體變化;PSPermGen表示gc回收前後永久區的記憶體變化。young gc 主要是針對年輕代進行記憶體回收比較頻繁,耗時短;full gc 會對整個堆記憶體進行回收,耗時長,因此一般儘量減少full gc的次數

  • 調優命令

    • Sun JDK監控和故障處理命令有jps jstat jmap jhat jstack jinfo
    • jps,JVM Process Status Tool,顯示指定系統內所有的HotSpot虛擬機器程式。
    • jstat,JVM statistics Monitoring是用於監視虛擬機器執行時狀態資訊的命令,它可以顯示出虛擬機器程式中的類裝載、記憶體、垃圾收集、JIT編譯等執行資料。
    • jmap,JVM Memory Map命令用於生成heap dump檔案
    • jhat,JVM Heap Analysis Tool命令是與jmap搭配使用,用來分析jmap生成的dump,jhat內建了一個微型的HTTP/HTML伺服器,生成dump的分析結果後,可以在瀏覽器中檢視
    • jstack,用於生成java虛擬機器當前時刻的執行緒快照。
    • jinfo,JVM Configuration info 這個命令作用是實時檢視和調整虛擬機器執行引數。
  • 調優工具

    • 常用的調優工具分為兩類jdk自帶監控工具:jconsole和jvisualvm第三方有:MAT(Memory Analyzer Tool)、GChisto。
      • jconsole,Java Monitoring and Management Console是從java5開始,在JDK中自帶的java監控和管理控制檯,用於對JVM中記憶體,執行緒和類等的監控
      • jvisualvm,jdk自帶全能工具,可以分析記憶體快照、執行緒快照;監控記憶體變化、GC變化等。 MAT,Memory Analyzer Tool,一個基於Eclipse的記憶體分析工具,是一個快速、功能豐富的Java heap分析工具,它可以幫助我們查詢記憶體洩漏和減少記憶體消耗
      • GChisto,一款專業分析gc日誌的工具
  1. Eden區和Survivo。

    • 每一個物件的建立跟分配都是在堆上面進行的,堆分為新生代,老生代。
    • 新生代有一個Eden和兩個Survivor(from,to)組成,預設比例是8:2。也可以使用-XXSurvivorRatio來改變百分比。
  2. JVM 引數

    jvm引數:

    • -Xms:初始堆大小
    • -Xmx:堆最大記憶體
    • -Xss:棧記憶體
    • -XX:PermSize 初始永久帶記憶體
    • -XX:MaxPermSize 最大永久帶記憶體
  3. 堆空間

    • 堆被劃分為:新生代、老年代
    • 堆大小 = 新生代 + 老年代
    • 新生代與老年代的比例值為1:2
    • 新生代中Edem:from:to = 8:1:1 即Eden = 8/10的新生代空間大小, from = to = 1/10的新生代空間大小
    • Minor GC 是發生在新生代中的垃圾收集動作,所採用的是複製演算法。
    • Full GC 是發生在老年代的垃圾收集動作,所採用的是標記-清除演算法。

相關文章