1. 程式人生 > >《JVM故障診斷指南》之1 —— JVM概覽與介紹

《JVM故障診斷指南》之1 —— JVM概覽與介紹

原文連結 原文作者:Byron Kiourtzoglou 翻譯:梅小西(904516706)

Oracle HotSpot JVM 記憶體

Java HotSpot 虛擬機器堆空間

這個部分將向你介紹Oracle Java HotSpot虛擬機器裡不同的Java堆記憶體空間概覽。理解這個對於任何一個涉及到線上經常出現的記憶體問題的解決非常重要。而具有合適的Java 虛擬機器堆空間的知識是很關鍵的。

Java虛擬機器是你Java程式的基礎,它提供了動態記憶體管理服務,垃圾收集,執行緒,IO以及本地操作等等。

Java堆空間是執行時Java程式的記憶體“容器”,它為你的Java程式提供了它需要的(Java堆,本地堆)合適的記憶體空間,並由JVM自身管理。

JVM HotSpot記憶體被分為3個記憶體空間:
• The Java Heap(堆)
• The PermGen (持久代)
• 本地堆(C-堆)

下面是他們的詳細分類:

記憶體空間 啟動引數和調整方法 監控方式 描述
Java 堆 -Xmx (最大堆容量)
-Xms (最小堆容量)

EX:
-Xmx1024m
-Xms1024m-verbose GC
– JMX API
– JConsole
– 其他監控工具Java堆是儲存你的主要
的Java程式Class例項。持久代-XX:MaxPermSize (最大容量)
-XX:PermSize (最小容量)

EX:
-XX:MaxPermSize=512m
-XX:PermSize=256m- verbose GC
– JMX API
– JConsole
– 其他監控工具Java HotSpot虛擬機器持久代空間
是一種JVM儲存,主要用於儲存
Class物件,如類名 ,類方法,
內部JVM物件和其他JIT優化
相關的資料。本地堆(C-堆)不支援直接配置。

對於32位的虛擬機器,
C堆容量= 4 Gig –堆 – 持久代

對於64位的虛擬機器,C堆容量=
伺服器總實體記憶體
&虛擬記憶體-堆-持久代- 在Windows 和Linux上檢查
整個程序大小
– Solaris 和Linux 下用pmap命令列
– AIX上用svmon命令C堆儲存各種物件如MMAP檔案,
其他JVM和第三方原生代碼物件。
Java堆空間 – 概覽 & 生命週期

你的Java程式生命週期通常看起來像這樣:
• Java 程式編碼(via Eclipse IDE etc.) ,例如 HelloWorld.java
• Java 程式編譯 (Java 編譯器或者第三方編譯工具如Apache Ant, Apache Maven..),例如 HelloWord.class
• Java 程式啟動和執行,例如通過HelloWorld.main() 方法執行。

現在我們來分析你的HelloWorld.class 程式,這樣你能更好理解。
• 啟動時,JVM會載入並把一些你的靜態程式以及JDK庫快取到本地堆裡面,包括本地庫,對映檔案比如你的程式Jar檔案,執行緒比如你的程式的主啟動執行緒等。
• JVM此時會儲存你的HelloWorld.class的“靜態”資料到持久代空間(Class元資料,描述資訊等)
• 一旦你的程式啟動,JVM開始管理,並在Java堆裡為程式動態的分配記憶體(年輕代和老年代),這也是為什麼瞭解你的程式需要多大記憶體空間是如此重要,你可以通過-Xms & -Xmx 的JVM引數恰當的調整你的Java堆大小。通過效能分析,堆轉儲分析允許你來決定程式的記憶體佔用。
• 最終,當你的程式不再需要記憶體時,JVM也會動態的從堆裡釋放記憶體,這叫垃圾收集。這個過程通過JVM verbose GC或者一個監控工具比如Jconsole能很容易的監控到。

Java HotSpot 虛擬機器持久代

Java HotSpot虛擬機器持久代是JVM用來儲存你的Java程式Class物件。Java堆主要用來儲存實際的短期或者長期的持久代Class物件例項。

持久代本身是完全靜態的,除非用第三方工具或者動態類載入中經常用到的Java反射API。

有一點很重要需要注意,這種記憶體儲存方式只應用在Java Hotspot虛擬機器上,其他的JVM比如IBM 和Oracle JRockit是沒有這種固定以及可配置的持久代儲存,它是用其他技術去管理非堆記憶體(本地記憶體)。

找到下面一張圖,它描述了JVM HotSpot Java堆 vs 持久代 並分析他們各自關聯的的屬性和容量引數調整。


這裡寫圖片描述

除了Oracle HotSpot JVM,還有其他各種供應商提供的虛擬機器。接下來的部分我們將分析其他JVM的記憶體配置。理解HotSpot和其他虛擬機器在實現和命名約定的不同也很重要。

IBM JVM 記憶體

IBM 虛擬機器 記憶體分為2個區域:
• Java堆 Heap (年輕空間和年老空間)
• 本地堆(C-Heap)

這是他們的分析:

記憶體空間 啟動引數和調整方法 監控方式 描述
Java 堆 -Xmx (最大堆容量)
-Xms (最小堆容量)
– verbose GC
– JMX API
– IBM 監控工具

EX:
-Xmx1024m
-Xms1024m

GC 策略Ex:
-Xgcpolicy:gencon
(使gencon GC 策略生效)

-verbose GC
– JMX API
– IBM監控工具IBM Java 堆通常分為年輕代和
年老代(YoungGen, OldGen).

年輕代 GC 策略 (聯合了併發和分代GC)
通常用於Java EE 平臺,為了最小化
GC暫停時間。本地堆 (C堆)不支援直接配置
對於32位虛擬機器,C堆容量
= 4 Gig – Java堆

對於64位虛擬機器,C堆容量 =
物理伺服器總記憶體 & 虛擬記憶體
– Java堆

– svmon 命令C堆用來儲存class元資料
物件,包括庫檔案,其他
JVM以及第三方原生代碼物件。
也許你也注意到,IBM的虛擬機器是沒有持久代的。持久代僅用於HotSpot虛擬機器。IBM虛擬機器是用本地堆儲存相關資料的Class元資料。
Oracle也開始打算將持久代從HotSpot裡去掉,我們在接下來的部分會討論。

Oracle JRockit JVM 記憶體

JRockit 虛擬機器記憶體分為2個部分:
• Java堆(年輕代和老年代)
• 本地記憶體空間(Class池,C堆,執行緒…)

記憶體空間 啟動引數和調整方法 監控方式 描述
Java 堆 -Xmx (最大堆容量)
-Xms (最小堆容量)

EX:
-Xmx1024m
-Xms1024m-verbose GC
– JMX API
– JRockit Mission
Control 工具集

JRockit Java堆通常分為年輕代
(短壽命物件)和年老代(長生命週期物件)。

本地記憶體空間不支援直接配置。

對32位虛擬機器,本地記憶體空間容量
= 2-4 Gig – Java堆

** 依據你作業系統的不同,程序
大小限制 2 GB, 3 GB 或 4 GB
**

對64位虛擬機器,本地記憶體空間容量
= 物理機總記憶體 &虛擬記憶體– Java堆

– 在Windows和Linux上
檢查總程序大小

– Solaris & Linux 的
pmap 命令列

– JRockit JRCMD 工具

JRockit本地記憶體空間用
於儲存Class元資料,執行緒
以及各種物件如庫檔案,
其他JVM和第三方原生代碼物件。
和IBM虛擬機器類似,JRockit也沒有持久代,它使用本地堆儲存相關對的Class元資料。

JRockit傾向於用更多的本地記憶體達到更好的效能。它沒有解釋模式,只有編譯模式,由於它多了本地記憶體,和同等大小的Sun JVM相比,程序需要的大小通常會大好幾百M 。但這不是一個大問題,除非你使用32位的JRockit並加上很大堆空間。這種方式下,對於JRockit(對於32位虛擬機器來說,堆越大留個本地堆的就越小)來說,OutOfMemoryError的危險性歸咎於本地堆消耗過高 。

HotSpot和JRockit的提供商Oracle的策略,是將這2個虛擬機器合成一個,並且包含2個的優點和特性。這也使得JVM調優變得簡單,因為未能理解這2個虛擬機器的不同會導致錯誤的調優建議和效能問題。

譯者介紹:
梅小西
Java工程師,關注JVM,併發程式設計,喜歡研究Python,Scala,Golang等。