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
jps //查看java進程
jps -l //顯示完整的類名
4.2 jinfo
jinfo -flag InitialHeapSize pid //查看初始堆內存
jinfo -flag MaxHeapSize pid //查看最大堆內存
jinfo -flag PermSize pid //查看初始分配的非堆內存
jinfo -flag MaxPermSize pid //查看最大允許分配的非堆內存
jinfo -flags pid //查看設置過值的參數
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里修改就可以了 。
————————————————
版權聲明:本文為CSDN博主「geekooler」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/geekooler/article/details/100852538
