JVM筆記

一、什麼是JVM:

  • Java虛擬機是一臺執行Java字節碼的虛擬計算機,它擁有獨立的運行機制,其運行的Java字節碼也未必是由Java語言編譯而成。

二、JVM的作用:

  • Java虛擬機就是二進制字節碼的運行環境,負責裝載字節碼到其內部,解釋編譯爲對應平臺的機器執行指令,每一條Java指令,Java虛擬機規範中都有詳細定義,如怎麼取操作,怎麼處理操作,處理結果放在那裏。

三、JVM的特點:

  • 一次編譯,導出運行
  • 自動內存管理
  • 自動垃圾回收功能

四、JVM種類:

  • Sun Classic VM:世界上第一框商用Java虛擬機JDK1.4時被完全淘汰。
  • Exact VM:JDK1.2時Sun公司提供該虛擬機,後被HotSpot虛擬機替換。
  • JRockit VM:該虛擬機號稱是世界上最快的JVM,因爲其內部不包含解釋器,所以速度確實快,2008年,開發該虛擬機的公司唄Oracle公司收購。
  • J9 VM:IBM公司研發,廣泛適用於IBM公司的各種Java產品。
  • HotSpot VM:目前HotSpot虛擬機佔有絕對的市場地位,不管是曾經大量使用的JDK6還是現在使用較多的JDK8中默認的虛擬機都是HotSpot,Sun JDK和Open JDK的默認虛擬機都是HotSpot。

五、JVM的整體結構:
JVM結構圖
1.程序計數器(Program Counter Register):

  • 介紹:它是程序控制流的指示器,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個計數器完成。

  • 作用:PC寄存器用來存儲指向下一條指令的地址,也即將要執行的指令代碼,由執行引擎讀取下一條指令。

2.Java虛擬機棧(Java stack):

  • 介紹:Java虛擬機棧(Java Virtual Machine Stack),早期也叫Java棧,每個線程在創建的時候都會創建一個虛擬機棧,其內部保存一個個的棧幀(Stack Frame),對應着一次次的Java 方法調用。(線程私有)。

  • 作用:主管Java程序的運行,它保存方法的局部變量(8種基本數據類型,對象的引 用地址)、部分結果、並參與方法的調用和返回。

  • 棧的特點:棧是一種快速有效的分配內存的方式,訪問速度僅次於程序計數器。Java直接對棧的操作只有兩個:每個方法的執行,伴隨着進棧(入棧、壓棧)、執行結束後的出棧工作。棧中不存在垃圾回收問題。

  • 棧中存儲的棧幀的內部結構:

  • 局部變量表(Local Variables)

  • 操作數棧(Operand Stack)(或表達式)

  • 動態鏈接(Dynamic Linking)(或指向運行時常量池的方法引用)

  • 方法返回值地址(Return Address)(或方法正常退出或者異常退出的定義)

  • 一些附加信息
    Java棧幀結構

3.本地方法棧

  • Java虛擬機用於管理Java方法的調用,而本地方法棧用於管理本地方法的調用。
    本地方法棧也是線程私有的,它由C語言實現
    本地方法棧的具體實現是Native Method Stack中登記native方法,在Execution Engine執行加載本地方法庫。

4.堆

  • 一個Java實例只存在一個堆內存,堆也是唯一Java內存管理的核心區域。
  • Java堆區在JVM啓動的時候即被創建,其空間大小也就確定了,是JVM管理中的最大一塊內存空間(堆的大小是可以調節的)。
  • 《Java虛擬機規範》規定,堆可以處於物理上不連續的內存空間中,但在邏輯上它應該是被視爲連續的。
  • 所有的線程共享Java堆,在這裏還可以劃分線程私有的緩衝區(Thread Local Allocation Buffer ,TLAB)。
  • 數組和對象可能永遠不會存儲在棧上,因爲棧幀中保存引用,這個引用指向對象或者數組在堆中的位置。
  • 在方法區結束後,堆中的對象不會馬上移除,僅僅在垃圾收集的時候纔會被移除。
  • 堆是GC(Carbage Collection。垃圾收集器)執行垃圾回收的重點區域
    類的實例化原理
  • 堆內存細分:新生區(Eden+Survivor1+Survivor2)+養老區+元空間(JDK7之前叫做永久區)
    堆空間結構

5.垃圾回收(GC):

  • JVM在進行GC時,並非每次都對三個內存(新生代、老年代、方法區)區域一起回收,大部分時候回收的都是新生代。
    針對HotSpot VM的實現,它裏面GC按照回收區域又分爲兩大種類型:一種是部分收集(Partial GC),一種是整堆收集(Full GC)
  • 部分收集:不是完整的收集整個Java堆的垃圾收集,其中又分爲:
  • 新生代收集(Minor GC / Young GC):只是新生代的垃圾收集。
  • 老年代收集(MaJor GC / Old GC): 只是老年代的垃圾收集。
  • 目前只有CMS GC 會有單獨收集老年代的行爲
  • 注意:很多時候Major GC 和 Full GC混淆使用,需要具體分辨是老年代回收還是整體回收。
  • 混合回收(Mixed GC):收集整個新生代以及部分老年代的垃圾收集(只有G1 GC會有這種行爲)
  • 整堆收集(Full GC):收集整個Java堆和方法區的垃圾收集。
  • 年輕代GC(Minor GC)觸發機制:
  • 當年輕代空間不足時,就會觸發Minor GC,這裏的年輕代滿指的是Eden滿,Survivor滿不會引發GC(每次Minor GC會清理年輕代的內存)
  • 因爲Java對象大多是具備朝生夕死的特性,所以Minor GC非常頻繁,一般回收速度也是比較快,這一定義即清晰又易於理解。
  • Minor GC會引發STW,暫停其它用戶的線程,等垃圾回收結束,用戶線程纔會恢復運行。
  • 老年代GC(Major GC / Full GC)觸發機制:
  • 指發生在老年代的GC,對象從老年代消失時,我們稱爲"Major GC" 或 "Full GC"發生了。
  • 出現了Major GC經常會伴隨至少一次的Minor GC(但非絕對的,在Parallel Scevenge收集器的手機策略裏就有直接進行Major GC的策略選擇過程。就是說在老年代空間不足時,會先嚐試觸發Minor GC,如果之後空間還不足,則會觸發Major GC)。
  • Major GC的速度一般會比Minor GC慢10倍以上,STW的時間更長。
  • 如果Major GC後,內存還是不足,就報OOM了。
  • Major GC的速度一般會比Minor GC慢10倍以上。
  • Full GC觸發機制
  • 1、調用System.gc()時,系統建議執行Full GC,但是不必然執行。
  • 2、老年代空間不足。
  • 3、方法區空間不足。
  • 4、通過Minor GC後進入老年代的平均大小大於老年代的可用內存。
  • 5、由Eden區、survivor space0(From Space)區向survivor space1(To Space)取複製時,對象大小大於To Space可用內存,則把該對象轉存到老年代,且老年代的可用內存小於該對象的大小。
  • 說明:Full GC是開發或調優中儘量要避免的,這樣暫停時間(STW)會短一些。

6.方法區

  • 方法區可以看做是一塊獨立於Java堆的內存結構。
  • 方法區(Method Area)與Java堆一樣,是各個線程共享的內存區域。
  • 方法區在JVM啓動的時候被創建,並且它的實際物理內存空間中和Java堆區一樣都可以是不連續的。
  • 方法區的大小,跟堆空間一樣,可以選擇固定大小或者可擴展。
  • 方法區的大小決定了系統可以保存多少個類,如果系統定義了太多的類,導致方法區溢出,虛擬機同樣會拋出內存溢出錯誤。
  • 關閉JVM就會釋放這個區域的內存。
  • 方法區的垃圾收集主要是回收兩部分內容,常量池中廢棄的常量和不再使用的類型。

7.執行引擎

  • 執行引擎的任務就是將字節碼指令解釋/編譯爲對應平臺上的本地機器指令,簡單來說,JVM中的執行引擎充當了將高級語言翻譯爲機器語言的譯者。