該文檔主要介紹JVM內存管理模型,垃圾回收算法,常用GC參數,JVM調優四部分內容。
一,內存管理模型
JVM將其使用的內存划分為如下幾個區域:
- 棧
- 本地方法站(native方法棧)
- 虛擬機棧(方法棧)
- 程序計數器(當前線程位置)
- Perm(運行時常量池,靜態方法,class對象等)
- 堆
- Young
- Eden
- S0
- S1:S1與S0相同大小
- Old
- Young
大而言之其實就是兩個部分:棧,堆。棧上空間一般都隸屬各個線程(方法區,常量池線程共享),意思是每個線程有自己的棧空間,其上主要是一些原始類型變量。堆區負責存放對象,因為這些對象90%都是短命對象,所以按照對象的生命長度將堆區划分為短命堆區(年輕代),和長命堆區(年老代)。
二,垃圾回收算法
有了上面按照不同的生命周期來划分的區域,所以JVM也有了按照生命周期來回收垃圾對象。
垃圾對象:沒有被根引用的對象
Young代回收算法:
因為Young代都是短命對象,一次YoungGC會回收大部分對象,只有少量會剩下來。ParNew采用多線程,Stop The World的方式,采用復制算法進行回收。
特點是:
- Stop The Workd
- 多線程並發回收
- 復制算法,內存回收后方便分配
Old代采用CMS回收算法:
回收步驟:
- 初始化清除:Stop The World 標記由根可以直達的對象
- 並發標記:並發標記可達對象
- 重新標記:Stop The World並發查找前一階段新生代晉升或者新分配,被更新的對象
- 並發清理
- 線程重置
優點:
- 低延遲
缺點:
- 因為是基於標記清除,容易產生碎片
三,常用GC參數
JVM parameters in Java
我們根據JVM參數以-X開頭或-XX開頭將JVM參數分成兩個部分:
1) 以-X開頭的都是非標准的(這些參數並不能保證在所有的JVM上都被實現),而且如果在新版本有什么改動也不會發布通知。
2)以-XX開頭的都是不穩定的並且不推薦在生產環境中使用。這些參數的改動也不會發布通知。
對響應時間要求很高的系統來說,良好掌握JVM關於GC調優的參數是很重要的。比如一個高流量低延遲的電子交易平台,他要求的響應時間都是毫秒級的。要獲得適合的參數組合需要大量的分析和不斷的嘗試,更依賴於交易系統的特性。
關於JVM選項的幾點:
1) 布爾型參數選項:-XX:+ 打開, -XX:- 關閉。(比如-XX:+PrintGCDetails)
2) 數字型參數選項通過-XX:<名稱>=<設定>。數字可以是 m/M(兆字節),k/K(千字節),g/G(G字節)。比如:32K表示32768字節。(比如-XX:-XX:NewRatio=4)
3) 字符行參數選項通過-XX:<名稱>=<設定>,通常用來指定一個文件,路徑,或者一個命令列表。(比如-XX:HeapDumpPath=./java_pid.hprof)
命令 java -help可以列出java 應用啟動時標准選項(不同的JVM實現是不同的)。java -X可以列出不標准的參數(這是JVM的擴展特性)。-X相關的選項不是標准的,被改變也不會通知。如果你想查看當前應用使用的JVM參數,你可以使用:ManagementFactory.getRuntimeMXBean().getInputArguments()。
下面就是經常用到的JVM參數列表。
1) 跟 Java 堆大小相關的 JVM 內存參數
2) 關於打印垃圾收集器詳情的 JVM 參數
-verbose:gc 記錄 GC 運行以及運行時間,一般用來查看 GC 是否是應用的瓶頸
-XX:+PrintGCDetails 記錄 GC 運行時的詳細數據信息,包括新生成對象的占用內存大小以及耗費時間等
-XX:-PrintGCTimeStamps 打印垃圾收集的時間戳
3) 設置 Java 垃圾收集器行為的 JVM 參數
-XX:+UseParallelGC 使用並行垃圾收集
-XX:-UseConcMarkSweepGC 使用並發標志掃描收集 (Introduced in 1.4.1)
-XX:-UseSerialGC 使用串行垃圾收集 (Introduced in 5.0.)
需要提醒的是,但你的應用是非常關鍵的、交易非常頻繁應用時,應該謹慎使用 GC 參數,因為 GC 操作是耗時的,你需要在這之中找到平衡點。4)JVM調試參數,用於遠程調試
-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000
5) 關於性能診斷的 JVM 參數
-Xprof
6) 關於類路徑方面的 JVM 參數
7) 用於修改 Perm Gen 大小的 JVM 參數
8) 用來跟蹤類加載和卸載的信息
-XX:+TraceClassLoading和 -XX:+TraceClassUnloading 用來打印類被加載和卸載的過程信息,這個用來診斷應用的內存泄漏問題非常有用。
-XX:+TraceClassLoading and -XX:+TraceClassUnloading print information class loads and unloads. Useful for investigating if you have a class leak or if old classes (like JITed Ruby methods in JRuby) are getting collected or not.You can read more about logging in Java on my post 10 Tips while logging in Java
10)用於調試目的的 JVM 開關參數
-XX:HeapDumpPath=./java_pid.hprof Path to directory or file name for heap dump.
-XX:-PrintConcurrentLocks Print java.util.concurrent locks in Ctrl-Break thread dump.
-XX:-PrintCommandLineFlags Print flags that appeared on the command line.
下面貼一份我們項目中用到的JVM參數(4core,8G):
1 /usr/local/java/bin/java -server -Dapp.key=api -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.io.tmpdir=/tmp 2 3 -Djava.net.preferIPv6Addresses=false 4 5 -Xmx4g -Xms4g -Xmn2g -XX:PermSize=128m 6 7 -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled 8 9 -XX:+ExplicitGCInvokesConcurrent -XX:CMSInitiatingOccupancyFraction=70 10 11 -XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSClassUnloadingEnabled 12 13 -XX:+TieredCompilation -XX:CICompilerCount=4 14 15 -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/opt/logs/mobile/groupapi/groupapi.gc.log -XX:ErrorFile=/opt/logs/mobile/groupapi/groupapi.vmerr.log 16 17 -XX:HeapDumpPath=/opt/logs/mobile/api/api.heaperr.log -Djetty.home= -Djetty.appkey=api 18 19 -Djetty.context=/ -Djetty.logs=/opt/logs/mobile/groupapi -Djetty.webroot=/opt/meituan/mobile/api/webroot com.sankuai.mms.boot.Bootstrap
四,JVM調優