天天看點

JVM參數檢視與設定

1    JVM記憶體管理的機制

1.1    堆(Heap)和非堆(Non-heap)記憶體

        按照官方的說法:“Java 虛拟機具有一個堆,堆是運作時資料區域,所有類執行個體和數組的記憶體均從此處配置設定。堆是在 Java 虛拟機啟動時建立的。”“在JVM中堆之外的記憶體稱為非堆記憶體(Non-heap memory)”。

        可以看出JVM主要管理兩種類型的記憶體:堆和非堆。簡單來說堆就是Java代碼可及的記憶體,是留給開發人員使用的;非堆就是JVM留給自己用的,

        是以方法區、JVM内部處理或優化所需的記憶體(如JIT編譯後的代碼緩存)、每個類結構(如運作時常數池、字段和方法資料)以及方法和構造方法的代碼都在非堆記憶體中。 

1.1.1    堆記憶體配置設定

        JVM初始配置設定的堆記憶體由-Xms指定,預設是實體記憶體的1/64;JVM最大配置設定的堆記憶體由-Xmx指定,預設是實體記憶體的1/4。預設空餘堆記憶體小于40%時,JVM就會增大堆直到-Xmx的最大限制;

        空餘堆記憶體大于70%時,JVM會減少堆直到-Xms的最小限制。是以伺服器一般設定-Xms、-Xmx 相等以避免在每次GC 後調整堆的大小。

        說明:如果-Xmx 不指定或者指定偏小,應用可能會導緻java.lang.OutOfMemory錯誤,此錯誤來自JVM,不是Throwable的,無法用try...catch捕捉。 

1.1.2    非堆記憶體配置設定

        JVM使用-XX:PermSize設定非堆記憶體初始值,預設是實體記憶體的1/64;由XX:MaxPermSize設定最大非堆記憶體的大小,預設是實體記憶體的1/4。(還有一說:MaxPermSize預設值和-server -client選項相關,

-server選項下預設MaxPermSize為64m,-client選項下預設MaxPermSize為32m。

        上面錯誤資訊中的PermGen space的全稱是Permanent Generation space,是指記憶體的永久儲存區域。XX:MaxPermSize設定過小會導緻java.lang.OutOfMemoryError: PermGen space 就是記憶體益出。 

        為什麼會記憶體溢出: 

(1)這一部分記憶體用于存放Class和Meta的資訊,Class在被 Load的時候被放入PermGen space區域,它和存放Instance的Heap區域不同。 

(2)GC(Garbage Collection)不會在主程式運作期對PermGen space進行清理,是以如果你的APP會LOAD很多CLASS 的話,就很可能出現PermGen space錯誤。

        這種錯誤常見在web伺服器對JSP進行pre compile的時候。

1.2    JVM記憶體限制(最大值)

        首先JVM記憶體限制于實際的最大實體記憶體,假設實體記憶體無限大的話,JVM記憶體的最大值跟作業系統有很大的關系。簡單的說就32位處理器雖然可控記憶體空間有4GB,但是具體的作業系統會給一個限制,

這個限制一般是2GB-3GB(一般來說Windows系統下為1.5G-2G,Linux系統下為2G-3G),而64bit以上的處理器就不會有限制了。

        為什麼有的機器我将-Xmx和-XX:MaxPermSize都設定為512M之後Eclipse可以啟動,而有些機器無法啟動?

通過上面對JVM記憶體管理的介紹我們已經了解到JVM記憶體包含兩種:堆記憶體和非堆記憶體,另外JVM最大記憶體首先取決于實際的實體記憶體和作業系統。是以說設定VM參數導緻程式無法啟動主要有以下幾種原因:

1) 參數中-Xms的值大于-Xmx,或者-XX:PermSize的值大于-XX:MaxPermSize;

2) -Xmx的值和-XX:MaxPermSize的總和超過了JVM記憶體的最大限制,比如目前作業系統最大記憶體限制,或者實際的實體記憶體等等。說到實際實體記憶體,這裡需要說明一點的是,如果你的記憶體是1024MB,但實際系統中用到的并不可能是1024MB,因為有一部分被硬體占用了。

2    JVM參數類型

2.1    JVM參數類型

1、    标準參數(-)

所有的JVM實作都必須實作這些參數的功能,而且向後相容。例如:-verbose:class(輸出jvm載入類的相關資訊,當jvm報告說找不到類或者類沖突時可此進行診斷);-verbose:gc(輸出每次GC的相關情況);-verbose:jni(輸出native方法調用的相關情況,一般用于診斷jni調用錯誤資訊)。

2、    非标準參數(-X)

預設jvm實作這些參數的功能,但是并不保證所有jvm實作都滿足,且不保證向後相容。例如:-Xms512m;-Xmx512m;-Xmn200m;-Xss128k;-Xloggc:file(與-verbose:gc功能類似,隻是将每次GC事件的相關情況記錄到一個檔案中,檔案的位置最好在本地,以避免網絡的潛在問題。若與verbose指令同時出現在指令行中,則以-Xloggc為準)。

3、    非Stable參數(-XX)

此類參數各個jvm實作會有所不同,将來可能會随時取消,需要慎重使用。例如:-XX:PermSize=64m;-XX:MaxPermSize=512m。

2.2    标準參數

1、 -help

2、-server -client

3、 -version -showversion

4、-cp -classpath

2.3    X參數

非标準化參數

-Xint : 解釋執行

-Xcomp:第一次使用就編譯成本地代碼

-Xmixed: 混合模式,JVM自己來決定是否編譯成本地代碼

2.4    XX參數

相對不穩定

主要用于JVM調優和Debug

XX參數分類:

1、Boolean類型

格式: -XX:[+-]<name> 表示啟用或者禁用name屬性

 比如: -XX:+UseConcMarkSweepGC

    -XX:UseG1GC

2、非Boolean類型

格式:  -XX:<name>=<value> 表示name屬性的值是value

比如:-XX:MaxGCPauseMillis=500

     XX:GCTimeRatio=19

3、 -Xmx -Xms

不是X參數,而是XX參數

-Xms等價于-XX:InitialHeapSize

-Xmx等價于-XX:MaxHeapSize

3    JVM參數檢視

3.1    檢視JVM運作時參數

-XX:+PrintFlagsInitial

-XX:+PrintFlagsFinal

-XX:+UnlockExperimentalVMOptions //解鎖實驗參數

-XX:+UnlockDiagnosticVMOptions //解鎖診斷參數

-XX:+PrintCommandLineFlags //列印指令行參數

-XX:+UseSerialGC,虛拟機運作在Client模式下的預設值,Serial+Serial Old。

-XX:+UseParallelGC,虛拟機運作在Server模式下的預設值,Parallel Scavenge+Serial Old(PS Mark Sweep)。

-XX:+UseParNewGC,ParNew+Serial Old,在JDK1.8被廢棄,在JDK1.7還可以使用。

-XX:+UseParallelOldGC,Parallel Scavenge+Parallel Old。

-XX:+UseConcMarkSweepGC,ParNew+CMS+Serial Old。

-XX:+UseG1GC,G1+G1,隻支援JDK1.7 14update以上

java -XX:+PrintCommandLineFlags -version //檢視jvm預設的垃圾回收器

3.2    參數使用

java -XX:+PrintFlagsInitial -version > PrintFlagsInitial.txt  //這個指令的值很多,儲存到檔案中

java -XX:+PrintFlagsFinal -version > PrintFlagsFinal.txt  

3.3    jps 檢視java程序

jps  //檢視java程序

jps -l  //顯示完整的類名

3.4    檢視正在運作的JVM參數

jinfo -flags pid   //檢視設定過值的參數

jinfo -flag InitialHeapSize pid   //檢視初始堆記憶體

jinfo -flag MaxHeapSize pid   //檢視最大堆記憶體

jinfo -flag PermSize pid     //檢視初始配置設定的非堆記憶體

jinfo -flag MaxPermSize pid     //檢視最大允許配置設定的非堆記憶體

jinfo -flag NewSize pid     //檢視年輕代初始記憶體

jinfo -flag MaxNewSize pid     //檢視年輕代最大記憶體

jinfo -flag NewRatio pid     //檢視年輕代與年老代的比值

jinfo -flag SurvivorRatio pid     //檢視年輕代中Eden區與Survivor區的比值

jinfo -flag MaxTenuringThreshold pid  //檢視對象如果在Survivor區移動了N次還沒有被垃圾回收就進入年老代

jinfo -flag UseSerialGC pid   //檢視串行收集器

jinfo -flag UseParallelGC pid   //檢視并行收集器

jinfo -flag UseParNewGC pid   //檢視并行收集器

jinfo -flag UseParallelOldGC pid   //檢視并行收集器

jinfo -flag UseConcMarkSweepGC pid   //檢視CMS回收器

jinfo -flag UseG1GC pid  //檢視G1回收器

jinfo -flag PrintGCDetails pid   //檢視是否列印GC日志

檢視JVM記憶體配置

jmap -heap pid > 1.txt  //參數較多,儲存到檔案 

4    JVM常用工具

4.1    jps

4.2    jinfo

jinfo -flag UseConcMarkSweepGC pid   //檢視垃圾回收器

jinfo -flag UseG1GC pid   //檢視垃圾回收器

jinfo -flag UseParallelGC pid   //檢視垃圾回收器

4.3 jmap

jmap -heap pid > 1.txt

5    Tomcat調優

5.1    Linux下修改TomcatJVM記憶體大小

要添加在tomcat 的bin 下catalina.sh 裡,位置cygwin=false前。

# OS specific support.  $var _must_ be set to either true or false.

JAVA_OPTS="-Xms256m -Xmx512m -Xss1024K -XX:PermSize=128m -XX:MaxPermSize=256m" 

cygwin=false

5.2    windows下修改Tomcat JVM記憶體大小

5.2.1 解壓版本的Tomcat , 要通過startup.bat啟動tomcat才能加載配置

要添加在tomcat 的bin 下catalina.bat 裡

rem Guess CATALINA_HOME if not defined

set CURRENT_DIR=%cd%後面添加

set JAVA_OPTS=-Xms1024m -Xmx1024m -Xmn=256m -XX:PermSize=128M -XX:MaxPermSize=128m -Djava.awt.headless=true  -XX:+UseSerialGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:D:\log\jvm\gc.log

5.2.2 安裝版的Tomcat ,沒有catalina.bat

安裝版的Tomcat下沒有catalina.bat

如果tomcat 6 注冊成了windows服務,或者windows2003下用tomcat的安裝版, 

在/bin/tomcat6w.exe裡修改就可以了 。