JVM總結


該文檔主要介紹JVM內存管理模型,垃圾回收算法,常用GC參數,JVM調優四部分內容。

一,內存管理模型

JVM將其使用的內存划分為如下幾個區域:

    • 本地方法站(native方法棧)
    • 虛擬機棧(方法棧)
    • 程序計數器(當前線程位置)
    • Perm(運行時常量池,靜態方法,class對象等)
  1. 堆 
    • Young
      • Eden
      • S0
      • S1:S1與S0相同大小
    • Old

大而言之其實就是兩個部分:棧,堆。棧上空間一般都隸屬各個線程(方法區,常量池線程共享),意思是每個線程有自己的棧空間,其上主要是一些原始類型變量。堆區負責存放對象,因為這些對象90%都是短命對象,所以按照對象的生命長度將堆區划分為短命堆區(年輕代),和長命堆區(年老代)。

二,垃圾回收算法

 有了上面按照不同的生命周期來划分的區域,所以JVM也有了按照生命周期來回收垃圾對象。

垃圾對象:沒有被根引用的對象

Young代回收算法:

因為Young代都是短命對象,一次YoungGC會回收大部分對象,只有少量會剩下來。ParNew采用多線程,Stop The World的方式,采用復制算法進行回收。

特點是:

  1. Stop The Workd
  2. 多線程並發回收
  3.  復制算法,內存回收后方便分配

Old代采用CMS回收算法:

 回收步驟:

  1. 初始化清除:Stop The World 標記由根可以直達的對象
  2. 並發標記:並發標記可達對象
  3. 重新標記:Stop The World並發查找前一階段新生代晉升或者新分配,被更新的對象
  4. 並發清理
  5. 線程重置

優點:

  • 低延遲

缺點:

  • 因為是基於標記清除,容易產生碎片 

三,常用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 內存參數

下面三個 JVM 參數用來指定堆的初始大小和最大值以及堆棧大小
  -Xms        設置 Java 堆的初始化大小
  -Xmx       設置最大的 Java 堆大小
  -Xss        設置Java線程堆棧大小
 -Xmn       設置新生代空間大小
-------------------------------------------------

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

-Xrunhprof
-------------------------------------------------

6) 關於類路徑方面的 JVM 參數

-Xbootclasspath用來指定你需要加載,但不想通過校驗的類路徑。JVM 會對所有的類在加載前進行校驗並為每個類通過一個int數值來應用。這個是保證 JVM 穩定的必要過程,但比較耗時,如果你希望跳過這個過程,就把你的類通過這個參數來指定。
-------------------------------------------------

7) 用於修改 Perm Gen 大小的 JVM 參數

下面的這三個參數主要用來解決 JVM 錯誤:  java.lang.OutOfMemoryError:Perm Gen Space.
-XX:PermSize and  -XX:MaxPermSize
-XX:NewRatio=2  Ratio of new/old generation sizes.
-XX:MaxPermSize=64m     Size of the Permanent Generation.
-------------------------------------------------

8) 用來跟蹤類加載和卸載的信息

-XX:+TraceClassLoading和 -XX:+TraceClassUnloading 用來打印類被加載和卸載的過程信息,這個用來診斷應用的內存泄漏問題非常有用。

-------------------------------------------------
9) JVM switches related to logging

-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

-XX:+PrintCompilation prints out the name of each Java method Hotspot decides to JIT compile. The list will usually show a bunch of core Java class methods initially, and then turn to methods in your application. In JRuby, it eventually starts to show Ruby methods as well
-------------------------------------------------

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調優

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM