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裡修改就可以了 。