JVM運行參數
常見標準參數
- -showversion: 顯示當前JVM版本等信息
- -D設置系統屬性參數:
/**
* 測試
* @author regotto
*/
public class JvmTest {
public static void main(String[] args) {
//獲取系統參數
String str = System.getProperty("str");
System.out.println(str);
}
}
在IDEA的運行配置環境中添加VM options
運行結果: hello
- server, client參數
server: 初始堆空間大, 並行垃圾回收, 啓動慢, 運行快
client: 初始堆空間小, 串行垃圾回收, 啓動快, 運行慢
默認64操作系統只有server類型
常見-X非標準參數
- -Xint: 強制JVM執行所有字節碼, 運行速度降低較爲嚴重
- -Xcomp: 與Xint相反, JVM第一次使用把所有的字節碼編譯生成本地代碼, 提高代碼優化程度(-Xcomp沒有讓JVM啓用JIT編譯器全部功能, JIT可以自行決定哪些代碼編譯, 哪些代碼不編譯), 也存在運行速度下降, 相比於Xint, -Xcomp較好
- -Xmixed: 解釋模式與編譯模式的混合, 讓JVM自行決定使用哪種方式進行編譯
常見-XX非標準參數(常用於JVM調優/debug操作)
boolean類型:
-XX:[+-]<name> +表示啓用屬性, -表示禁用屬性
例: -XX:+DisableExplicitGC 禁止手動調用GC
非boolean類型:
-XX:<name>=<value> 設置name值爲value
例: -XX:NewRatio=1 設置新老代比值
- -Xms: 設置jvm的堆內存大小, 例: -Xms512m 等價於 -XX: InitialHeapSize=512m
- -Xmx: 設置堆內存最大值, 例: -Xmx2048m 等價於 -XX: MaxHeapSize=2048m
查看JVM運行參數
- 運行時打印參數: -XX:+PrintFlagsFinal
查詢打印的運行參數如下:
根據上圖, 等號後面是數字 => 非boolean類型-XX參數; 等號後面是true/false => boolean類型-XX:參數; =, :=代表默認值與被修改的值 - 查看正在運行的JVM參數: jinfo -flags 進程端口; 查看指定屬性的值: jinfo -flags 屬性 進程端口
JVM內存模型
1.7版本與1.8版本內存模型
各區域說明
Young: 年輕代=> 包含Eden, 2*Survivor, 其中一個Survivor用於存放GC時存活的對象, 經歷幾次垃圾回收, Survivor中存活對象轉移到Tenured
Tenured: 老年代存放生命週期長的對象, 對象在Young中區域中, 經歷多次GC都還存活, 才能轉移到Tenured, 當生產一個大對象時, 會直接移動到老年代中
Perm: 1.7版本, 保存class, method, field對象. 很少出現OOM
MetaspaceVM: 1.8版本, 使用元數據空間替換Perm區, 存放位置放置在直接內存中, 不再佔用虛擬機空間
Virtual: 最大內存與初始內存的差值
棄用1.7Perm永久區說明
根據官方說明: 融合HotSpot, JRockit(不存在永久代), 且永久代容易出現OOM
jstat使用
jstat: 用於查詢堆內存各部分使用情況, 加載類數量
Loaded: 加載class數量 Bytes: 佔用空間大小 Unloaded: 未加載數量 Bytes: 未加載空間 Time: 時間
查看當前應用編譯情況
Compiled:編譯數量。 Failed:失敗數量 Invalid:不可用數量 Time:時間 FailedType:失敗類型 FailedMethod:失敗的方法
查看當前應用GC情況
S0C:第一個Survivor區的大小(KB) S1C:第二個Survivor區的大小(KB) S0U:第一個Survivor區的使用大小(KB) S1U:第二個Survivor區的使用大小(KB)
EC:Eden區的大小(KB) EU:Eden區的使用大小(KB) OC:Old區大小(KB) OU:Old使用大小(KB)
MC:方法區大小(KB) MU:方法區使用大小(KB) CCSC:壓縮類空間大小(KB) CCSU:壓縮類空間使用大小(KB)
YGC:年輕代垃圾回收次數 YGCT:年輕代垃圾回收消耗時間
FGC:老年代垃圾回收次數 FGCT:老年代垃圾回收消耗時間 GCT:垃圾回收消耗總時間
動態查看應用運行情況: jstat -gc 13880 1000 5 => 每隔1s打印一次, 總共打印5次
jmap使用
jmap: 相比於jstat, jmap能獲取更加詳細的內容
查看當前應用堆情況:
查看應用存活對象:
jmap -histo 105772 代表查看所有對象, 包括死亡的對象
對象說明:
B byte
C char
D double
F float
I int
J long
Z boolean
[ 數組,如[I表示int[] [L+類名 其他對象
將內存使用情況dump到文件中, jhat對dump文件分析
jmap -dump:format=b, file=dumpFileName 應用端口
jhat -port 端口 dump文件
可以對上面的內容進行檢查, 快速定位分析問題, 哪個地方有大對象產生, 那個地方的內存分配不合理等情況
模擬內存溢出, 使用Eclipse Memory Analyzer進行分析
import java.util.ArrayList;
import java.util.UUID;
/**
* 內存溢出測試
* @author regotto
*/
public class JvmTestOutOfMemarry {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<String>();
for (int i = 0; i < 10000000; i++) {
String s = "";
for (int j = 0; j < 10000; j++) {
s += UUID.randomUUID().toString();
}
strings.add(s);
}
System.out.println("Ok");
}
}
-XX:HeapDumpOnOutOfMemoryError: 設置程序內存溢出時, 自動生成dump文件
將在項目下生成的java_pid175420.hprof導入Eclipse Memory Analyzer工具
查看分析報告: 在main函數中, 存在本地變量佔用73.09%的內存空間, 點擊see stacktrace查看線程棧調用情況, 如下圖, 可以看出StringBuilder.append導致內存溢出情況
jstack查看jvm線程情況
jstack pid
Java VisualVM
使用方式 => 自行百度
注: 監控遠程服務器上的程序, 需要配置JMX才能進行JMX連接