一、檢視jvm常用指令
jinfo:可以輸出并修改運作時的java 程序的opts。
jps:與unix上的ps類似,用來顯示本地的java程序,可以檢視本地運作着幾個java程式,并顯示他們的程序号。
jstat:一個極強的監視VM記憶體工具。可以用來監視VM記憶體内的各種堆和非堆的大小及其記憶體使用量。
jmap:列印出某個java程序(使用pid)記憶體内的所有'對象'的情況(如:産生那些對象,及其數量)。
jconsole:一個java GUI監視工具,可以以圖表化的形式顯示各種資料。并可通過遠端連接配接監視遠端的伺服器VM。
需要注意:在使用這些工具前,先用JPS指令擷取目前的每個JVM程序号,然後選擇要檢視的JVM。
二、jinfo
jinfo可以檢視設定的jvm的資訊
jinfo -flag MaxHeapSize [pid] 能夠檢視最大堆記憶體
jinfo -flag ThreadStackSize [pid]
jinfo -flags [pid]
jinfo -flag UseConcMarkSweepGC [pid]
jinfo -flag UseG1GC [pid]
jinfo -flag UseParallelGC [pid]
三、檢視jvm運作時的參數
1)java -XX:+PrintFlagsFinal -version
得出的結果,如果是
= 表示預設值
:= 表示被使用者或者jvm修改後的值
2)-XX:+UnlockDiagnosticVMOptions 解鎖診斷參數
-XX:+PrintCommandLineFlags 列印指令行參數
3)jps
jps這個沒什麼好說的,在linux裡面ps是檢視程序,jps就是java的ps,檢視java程序
如果執行"jps -l"就能檢視整個類名
四、jstat
這個指令用來檢視jvm統計資訊,主要分以下三類:
1)類裝載
jstat -class [pid] 1000 10
這個指令指的是每1秒(1000就是1000ms)檢視一次類的裝載資訊,一共看十次。後面的1000和10可以不要
2)垃圾收集
-gc、-gcutil、-gccause、-gcnew、-gcold
3)JIT編譯
jstat -compiler [pid]
jstat -printcompilation [pid]
五、jmap
jmap是一個很重要的指令,可以檢視jvm記憶體使用情況。可以分為兩點講解:
1)導出記憶體映像檔案
記憶體溢出自動導出,設定參數既可:
+XX:HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./
不用多說,設定記憶體溢出自動導出還有導出的路徑
使用jmap指令手動導出:
jmap -dump:format=b,file=heap.hprof [pid]
其中format=b代表用二進制導出
2)檢視記憶體映像檔案:
在這裡http://www.eclipse.org/mat/downloads.php下載下傳記憶體分析工具,然後把dump檔案導入分析就可以了。
六 、jstack
jstack也是一個很重要的指令,可以檢視線程使用情況。這裡需要知道現場的幾種狀态,參考如下:
- NEW狀态: The thread has not yet started.
- RUNNABLE狀态:The thread is executing in the JVM.
- BLOCKED狀态:The thread is blocked waiting for a monitor lock.
- WAITING狀态:The thread is waiting indefinitely for another thread to perform a particular action.
- TIMED_WAITING狀态:The thread is waiting for another thread to perform an action for up to a specified waiting time.
- TERMINATED狀态:The thread has exited.
狀态之間是怎麼轉換的呢?參考如下:
jvm裡面檢視線程使用情況的指令"jstack [pid]",将得到的線程情況輸入一個叫做stack.txt的檔案:
這個stack.txt檔案能夠檢視到jvm裡面某個id的線程是用來做什麼的?如果發生了死鎖,在最後也會列舉出來。
在linux裡面怎麼知道線程線上執行的情況呢,哪些線程占用了很大的記憶體呢?
這時可以用這個指令 "top -p [pid] -H" 就能夠看到單個程序裡面線程的情況:
通過printf "%x" [pid] 可以将10精緻的pid 轉換為16進制,轉換成16進制有什麼用?
因為jstack出來的線程是十六進制的,通過剛剛那個值,就能夠在jstack出來的檔案裡面找到使用記憶體最多的線程是哪一個線程了。
七、jvisualvm
jvisualvm是一個可視化工具,內建了上面指令的幾乎所有功能,但是它更加直覺,是以jvisualvm也很重要。它也在jdk目錄的bin目錄下。監控本地應用很簡單,直接打開jvisualvm就能看到有本地的了。下面着重介紹監控遠端的:
1)監控遠端tomcat
修改tomcat的Catalina.sh
JAVA_OPTS='-Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.1.54'
參數說明:
第一個參數是端口,不用說;
第二個參數是不需要ssl驗證,連結的時候不勾那個屬性
第三個參數是不需要驗證
第四個參數是這個tomcat應用的位址,注意不是jvisualvm的位址。
2)監控遠端java應用:
nohup java
-Dcom.sun.management.jmxremote
-Djava.rmi.server.hostname=192.168.1.54
-Dcom.sun.management.jmxremote.port=12344
-Dcom.sun.management.jmxremote.ssl=false -
Dcom.sun.management.jmxremote.authenticate=false
-Djava.net.preferIPv4Stack=true
-jar test.jar
指令是一樣的,但是一定要記住的是這裡的192.168.1.54一定是我們的java的應用位址,而不是jvisual的位址!!
記得開放端口, 然後把需要的添加的機器192.168.1.54添加到jvisualvm的"遠端"标簽裡面,然後在“遠端“标簽裡面添加端口在ip後面就可以。
這裡說一下監控遠端可能會有一點坑,原因如下:
1)首先確定在java應用的機器裡面可以使用jvisualvm才可以,也就是在java應用的機器裡面調用jvisualvm沒有報錯(可能隻是warning),才可以。
2)可能是jdk版本的問題。有可能确認了多少遍端口和應用的問題,但是就是連不上,是以就要看看是不是jdk版本的問題(也許不是,是以就在需要監控的java應用程式的機器上先試下jvisualvm)
JVM性能優化建議
一、JVM堆記憶體劃分
JDK7及以前的版本:一個對象被建立以後首先被放到Nursery記憶體中的Eden内 存中,如果存活期超兩個Survivor之後就會被轉移到長時記憶體中(Old Generation)中。永久記憶體中存放着對象的方法、變量等中繼資料資訊。通過如果永久記憶體不夠,就會得到如下錯誤:Java.lang.OutOfMemoryError: PermGen
JDK8版本:JDK8中把存放中繼資料中的永久記憶體從堆記憶體中移到了本地記憶體(native memory)中,這樣永久記憶體就不再占用堆記憶體,它可以通過自動增長來避免JDK7以及前期版本中常見的永久記憶體錯誤(java.lang.OutOfMemoryError: PermGen)。JDK8也提供了一個新的設定Matespace記憶體大小的參數:
-XX:MaxMetaspaceSize=128m
需要注意:如果不設定Matespaces記憶體大小參數,JVM将會根據一定的政策自動增加本地元記憶體空間。如果你設定的元記憶體空間過小,你的應用程式可能得到以下錯誤:java.lang.OutOfMemoryError: Metadata space
二、JVM參數
-XX 參數被稱為不穩定參數,此類參數的設定很容易引起JVM性能上的差異。
1)不穩定參數文法規則
布爾類型
-XX:+<option> '+'表示啟用該選項
-XX:-<option> '-'表示關閉該選項
數字類型
-XX:<option>=<number>
# 可跟随機關,例如:'m'或'M'表示兆位元組;'k'或'K'千位元組;'g'或'G'千兆位元組。32K與32768是相同大小的。
字元串類型
-XX:<option>=<string>
# 通常用于指定一個檔案、路徑或一系列指令清單。例如:-XX:HeapDumpPath=./dump.core
2)行為選項
選項 | 預設值 | 描述 |
-XX:-AllowUserSignalHandlers | 限于Linux和Solaris預設關閉 | 允許為java程序安裝信号處理器。 |
-XX:AltStackSize=16384 | 僅适用于Solaris,從5.0中删除 | 備用信号堆棧大小(以位元組為機關) |
-XX:-DisableExplicitGC | 預設關閉 | 禁止在運作期顯式地調用 System.gc()。注意:你熟悉的代碼裡沒調用System.gc(),不代表你依賴的架構工具沒在使用。 |
-XX:+FailOverToOldVerifier | Java6新引入選項,預設啟用 | 如果新的Class校驗器檢查失敗,則使用老的校驗器。解決相容性問題。 關聯選項:-XX:+UseSplitVerifier |
-XX:+HandlePromotionFailure | Java1.5以前預設關閉,Java1.6後預設啟用 | 新生代收集擔保,于年老代預留記憶體。 |
-XX:+MaxFDLimit | 限于Solaris,預設啟用 | 設定java程序可用檔案描述符為作業系統允許的最大值。 |
-XX:PreBlockSpin | 預設10 | 控制多線程自旋鎖優化的自旋次數 前置選項: -XX:+UseSpinning |
-XX:-RelaxAccessControlCheck | 預設關閉,Java1.6引入 | 在Class校驗器中,放松對通路控制的檢查。作用與reflection裡的setAccessible類似。 |
-XX:+ScavengeBeforeFullGC | 預設啟用 | 在Full GC前觸發一次Minor GC |
-XX:+UseAltSigs | 限于Solaris | 為了防止與其他發送信号的應用程式沖突,允許使用候補信号替代 SIGUSR1和SIGUSR2。 |
-XX:+UseBoundThreads | 綁定所有的使用者線程到核心線程。 減少線程進入饑餓狀态(得不到任何cpu time)的次數。 | |
-XX:-UseConcMarkSweepGC | 預設關閉,Java1.4引入 | 啟用CMS低停頓垃圾收集器。 |
-XX:+UseGCOverheadLimit | 預設啟用,Java1.6引入 | 限制GC的運作時間。如果GC耗時過長,就抛OutOfMemoryError。 |
-XX:+UseLWPSynchronization | 限于solaris, 預設啟用, Java1.4引入 | 使用輕量級程序(核心線程)替換線程同步。 |
-XX:-UseParallelGC | -server時啟用, 其他情況下:預設關閉, Java1.4引入 | 為新生代使用并行清除,年老代使用單線程Mark-Sweep-Compact的垃圾收集器。 |
-XX:-UseParallelOldGC | 預設關閉, Java1.5引入 | 為老年代和新生代都使用并行清除的垃圾收集器。開啟此選項将自動開啟-XX:+UseParallelGC 選項 |
-XX:-UseSerialGC | -client時啟用, 預設關閉, Java1.5引入 | 使用串行垃圾收集器。 |
-XX:-UseSpinning | Java1.4.2和1.5需要手動啟用, Java1.6預設已啟用 | 啟用多線程自旋鎖優化。關聯選項:-XX:PreBlockSpin=10 |
-XX:+UseTLAB | Java1.4.2以前和使用-client選項時:預設關閉, 其餘版本預設啟用 | 啟用線程本地緩存區(Thread Local) |
-XX:+UseSplitVerifier | Java1.5預設關閉, Java1.6預設啟用 | 使用新的Class類型校驗器 。關聯選項: -XX:+FailOverToOldVerifier |
-XX:+UseThreadPriorities | 使用本地線程的優先級。 | |
-XX:+UseVMInterruptibleIO | 限于solaris, 預設啟用, Java1.6引入 | 在solaris中,允許運作時中斷線程 |
3)性能選項
-XX:+AggressiveOpts | Java1.5 引入,預設關閉,Java1.6後預設開啟 | 開啟編譯器性能優化。 |
-XX:CompileThreshold=10000 | 預設值:1000 | 通過JIT編譯器,将方法編譯成機器碼的觸發閥值,可以了解為調用方法的次數,例如調1000次,将方法編譯為機器碼。 [-client: 1,500] |
-XX:LargePageSizeInBytes=4m | 預設值:4m,amd64位:2m | 設定堆記憶體的記憶體最大值。 |
-XX:MaxHeapFreeRatio=70 | 預設70 | GC後,如果發現空閑堆記憶體占到整個預估上限值的70%,則收縮預估上限值。 |
-XX:MaxNewSize=size | 1.3.1 Sparc: 32m,1.3.1 x86: 2.5m | 新生代占整個堆記憶體的最大值。從Java1.4開始, MaxNewSize成為 NewRatio的一個函數 |
-XX:MaxPermSize=64m | Java1.5以後::64 bit VMs會增大預設值的30%,1.4 amd64::96m,1.3.1 -client: 32m,其他預設 64m | Perm(俗稱方法區)占整個堆記憶體的最大值。 |
-XX:MinHeapFreeRatio=40 | 預設值:40 | GC後,如果發現空閑堆記憶體占到整個預估上限值的40%,則增大上限值。關聯選項:-XX:MaxHeapFreeRatio=70 |
-XX:NewRatio=2 | Sparc -client: 8,x86 -server: 8 ,x86 -client: 12 -client: 4 (1.3) 8 (1.3.1+) ,x86: 12 ,其他:2 | 新生代和年老代的堆記憶體占用比例。 例如2表示新生代占年老代的1/2,占整個堆記憶體的1/3。 |
-XX:NewSize=2m | 5.0以後: 64 bit Vms 會增大預設值的30%,x86: 1m,x86, 5.0以後: 640k,其他:2.125m | 新生代預估上限的預設值。 |
-XX:ReservedCodeCacheSize=32m | Solaris 64-bit, amd64, -server x86: 48m ,1.5.0_06之前, Solaris 64-bit ,amd64: 1024m ,其他:32m | 設定代碼緩存的最大值,編譯時用。 |
-XX:SurvivorRatio=8 | Solaris amd64: 6 ,Sparc in 1.3.1: 25 ,Solaris platforms 5.0以前: 32 ,其他:8 | Eden與Survivor的占用比例。例如8表示,一個survivor區占用 1/8 的Eden記憶體,即1/10的新生代記憶體,為什麼不是1/9? 因為我們的新生代有2個survivor,即S1和S22。是以survivor總共是占用新生代記憶體的 2/10,Eden與新生代的占比則為 8/10。 |
-XX:TargetSurvivorRatio=50 | 預設值:50 | 實際使用的survivor空間大小占比。預設是47%,最高90%。 |
-XX:ThreadStackSize=512 | Sparc: 512 ,Solaris x86: 320 (5.0以前 256) ,Sparc 64 bit: 1024 Linux amd64: 1024 (5.0 以前 0) ,其他:512. | 線程堆棧大小, |
-XX:+UseBiasedLocking | Java1.5 update 6後引入,預設關閉。Java1.6預設啟用。 | 啟用偏向鎖 |
-XX:+UseFastAccessorMethods | 優化原始類型的getter方法性能。 | |
-XX:-UseISM | 啟用solaris的ISM | |
-XX:+UseLargePages | Java1.5 update 5後引入,預設關閉,Java1.6預設啟用 | 啟用大記憶體分頁。關聯選項:-XX:LargePageSizeInBytes=4m |
-XX:+UseMPSS | Java1.4.1 之前預設關閉,其他版本預設啟用 | 啟用solaris的MPSS,不能與ISM同時使用。 |
-XX:+UseStringCache | 預設開啟 | 緩存常用字元串。 |
-XX:AllocatePrefetchLines=1 | 預設值:1 | 在使用JIT生成的預讀取指令配置設定對象後讀取的緩存行數。如果上次配置設定的對象是一個執行個體則預設值是1,如果是一個數組則是3 |
-XX:AllocatePrefetchStyle=1 | 預讀取指令的生成代碼風格,0- 無預讀取指令生成 ,1-在每次配置設定後執行預讀取指令 ,2-當預讀取指令執行後使用TLAB()配置設定水印指針來找回入口, | |
-XX:+UseCompressedStrings | Java1.6 update 21引入 | 其中,對于不需要16位字元的字元串,可以使用byte[] 而非char[]。對于許多應用,這可以節省記憶體,但速度較慢(5%-10%) |
-XX:+OptimizeStringConcat | Java1.6 update 20引入 | 在可能的情況下優化字元串連接配接操作。 |
4)調試選項
-XX:-CITime | 列印JIT編譯器編譯耗時。 | |
-XX:ErrorFile=./hs_err_pid.log | Java1.6引入 | 如果JVM crashed,将錯誤日志輸出到指定檔案路徑。 |
-XX:-ExtendedDTraceProbes | Java6引入,限于solaris,預設關閉 | 啟用dtrace診斷 |
-XX:HeapDumpPath=./java_pid.hprof | 預設是java程序啟動位置 | 堆記憶體快照的存儲檔案路徑。 |
-XX:-HeapDumpOnOutOfMemoryError | 在java.lang.OutOfMemoryError 異常出現時,輸出一個dump.core檔案,記錄當時的堆記憶體快照(見 -XX:HeapDumpPath 的描述) | |
-XX:OnError=”\;\” | Java1.4引入 | 當java每抛出一個ERROR時,運作指定指令行指令集。指令集是與OS環境相關的,在Linux下多數是.sh腳本,windows下是.bat批處理。 |
-XX:OnOutOfMemoryError=”\;\” | Java1.4.2 update 12和Java6時引入 | 當第一次發生java.lang.OutOfMemoryError 時,運作指定指令行指令集。指令集是與OS環境相關的,在linux下多數是.sh腳本,windows下是.bat批處理。 |
-XX:-PrintClassHistogram | 在Windows下, 按ctrl-break或Linux下是執行kill -3(發送SIGQUIT信号)時,列印class柱狀圖。 jmap -histo pid也實作了相同的功能。 | |
-XX:-PrintConcurrentLocks | 在thread dump的同時,列印java.util.concurrent的鎖狀态。jstack -l pid 也同樣實作了同樣的功能。 | |
-XX:-PrintCommandLineFlags | Java1.5 引入,預設關閉 | Java啟動時,往stdout列印目前啟用的非穩态jvm options。 例如:-XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError -XX:+DoEscapeAnalysis |
-XX:-PrintCompilation | 往stdout列印方法被JIT編譯時的資訊。 | |
-XX:-PrintGC | 開啟GC日志列印。顯示結果例如: [Full GC 131115K->7482K(1015808K), 0.1633180 secs] ,該選項可通過com.sun.management.HotSpotDiagnosticMXBean API 和 jconsole 動态啟用。 | |
-XX:-PrintGCDetails | Java1.4引入,預設關閉 | 列印GC回收的詳細資訊。 顯示結果例如: [Full GC (System) [Tenured: 0K->2394K(466048K), 0.0624140 secs] 30822K->2394K(518464K), [Perm : 10443K->10443K(16384K)], 0.0625410 secs] [Times: user=0.05 sys=0.01, real=0.06 secs] ,該選項可通過com.sun.management.HotSpotDiagnosticMXBean API 和 jconsole 動态啟用。 |
-XX:-PrintGCTimeStamps | 列印GC停頓耗時。 顯示結果例如: 2.744: [Full GC (System) 2.744: [Tenured: 0K->2441K(466048K), 0.0598400 secs] 31754K->2441K(518464K), [Perm : 10717K->10717K(16384K)], 0.0599570 secs] [Times: user=0.06 sys=0.00, real=0.06 secs] ,該選項可通過com.sun.management.HotSpotDiagnosticMXBean API 和 jconsole 動态啟用。 | |
-XX:-PrintTenuringDistribution | 列印對象的存活期限資訊。 顯示結果例如: [GC Desired survivor size 4653056 bytes, new threshold 32 (max 32) - age 1: 2330640 bytes, 2330640 total - age 2: 9520 bytes, 2340160 total 204009K->21850K(515200K), 0.1563482 secs] ,Age1,2表示在第1和2次GC後存活的對象大小。 | |
-XX:-TraceClassLoading | 列印class裝載資訊到stdout。記Loaded狀态。 例如: [Loaded java.lang.Object from /opt/taobao/install/jdk1.6.0_07/jre/lib/rt.jar] | |
-XX:-TraceClassLoadingPreorder | 1.4.2引入,預設關閉 | 按class的引用/依賴順序列印類裝載資訊到stdout。不同于 TraceClassLoading,本選項隻記 Loading狀态。 例如: [Loading java.lang.Object from /home/confsrv/jdk1.6.0_14/jre/lib/rt.jar] |
-XX:-TraceClassResolution | 列印所有靜态類,常量的代碼引用位置。用于debug。 例如: RESOLVE java.util.HashMap java.util.HashMapEntryHashMap.java:209<br>說明HashMap類的209行引用了靜态類java.util.HashMapEntryHashMap.java:209<br>說明HashMap類的209行引用了靜态類java.util.HashMapEntry | |
-XX:-TraceClassUnloading | 列印class的解除安裝資訊到stdout。記Unloaded狀态。 | |
-XX:-TraceLoaderConstraints | Java1.6 引入,預設關閉 | 列印class的裝載政策變化資訊到stdout。裝載政策變化是實作classloader隔離/名稱空間一緻性的關鍵技術。 |
-XX:+PerfSaveDataToFile | 當java程序因java.lang.OutOfMemoryError 異常或crashed 被強制終止後,生成一個堆快照檔案。 | |
-XX:ParallelGCThreads=n | 預設值:随JVM運作平台不同而異 | 配置并行收集器的線程數,即:同時多少個線程一起進行垃圾回收。此值最好配置與處理器數目相等。 |
-XX:+UseCompressedOops | 32位預設關閉,64位預設啟動 | 使用compressed pointers。這個參數預設在64bit的環境下預設啟動,但是如果JVM的記憶體達到32G後,這個參數就會預設為不啟動,因為32G記憶體後,壓縮就沒有多大必要了,要管理那麼大的記憶體指針也需要很大的寬度了 |
-XX:+AlwaysPreTouch | 在JVM 初始化時預先對Java堆進行摸底。 | |
-XX:AllocatePrefetchDistance=n | 預設值取決于目前JVM 設定 | 為對象配置設定設定預取距離。 |
-XX:InlineSmallCode=n | 當編譯的代碼小于指定的值時,内聯編譯的代碼。 | |
-XX:MaxInlineSize=35 | 預設值:35 | 内聯方法的最大位元組數。 |
-XX:FreqInlineSize=n | 内聯頻繁執行的方法的最大位元組碼大小。 | |
-XX:LoopUnrollLimit=n | 代表節點數目小于給定值時打開循環體。 | |
-XX:InitialTenuringThreshold=7 | 預設值:7 | 設定初始的對象在新生代中最大存活次數。 |
-XX:MaxTenuringThreshold=n | 預設值:15,最大值:15 | 設定對象在新生代中最大的存活次數,最大值15,并行回收機制預設為15,CMS預設為4。 |
-Xloggc: | 輸出GC 詳細日志資訊至指定檔案。 | |
-XX:-UseGCLogFileRotation | 開啟GC 日志檔案切分功能,前置選項 -Xloggc | |
-XX:NumberOfGClogFiles=1 | 必須>=1,預設值:1 | 設定切分GC 日志檔案數量,檔案命名格式:.0, .1, …, .n-1 |
-XX:GCLogFileSize=8K | 必須>=8K,預設值:8K | GC日志檔案切分大小。 |
三、垃圾收集器
1. 串行回收器
1.1)新生代串行回收器
特點
- 它僅僅使用單線程進行垃圾回收
- 它是獨占式的垃圾回收
- 進行垃圾回收時, Java應用程式中的線程都需要暫停(Stop-The-World)
- 使用複制算法
- 适合CPU等硬體不是很好的場合
設定參數
-XX:+UseSerialGC 指定新生使用新生代串行收集器和老年代串行收集器, 當以client模式運作時, 它是預設的垃圾收集器
1.2)老年代串行回收器
- 同新生代串行回收器一樣, 單線程, 獨占式的垃圾回收器
- 通常老年代垃圾回收比新生代回收要更長時間, 是以可能會使應用程式停頓較長時間
-XX:+UseSerialGC 新生代, 老年代都使用串行回收器
-XX:+UseParNewGC 新生代使用ParNew回收器, 老年代使用串行回收器
-XX:+UseParallelGC 新生代使用ParallelGC回收器, 老年代使用串行回收器
2. 并行回收器
2.1)新生代ParNew回收器
- 将串行回收多線程化
- 垃圾回收時, 應用程式仍會暫停, 隻不過由于是多線程回收, 在多核CPU上,回收效率會高于串行回收器, 反之在單核CPU, 效率會不如串行回收器
-XX:+UseParNewGC 新生代使用ParNew回收器, 老年代使用串行回收器
-XX:+UseConcMarkSweepGC 新生代使用ParNew回收器, 老年代使用CMS回收器
-XX:ParallelGCThreads=n 指回ParNew回收器工作時的線程數量, cpu核數小時8時, 其值等于cpu數量, 高于8時,可以使用公式(3+((5*CPU_count)/8))
2.2)新生代ParallelGC回收器
- 同ParNew回收器一樣, 不同的地方在于,它非常關注系統的吞吐量(通過參數控制)
- 支援自适應的GC調節政策
-XX:+UseParallelGC 新生代用ParallelGC回收器, 老年代使用串行回收器
-XX:+UseParallelOldGC 新生代用ParallelGC回收器, 老年代使用ParallelOldGC回收器系統吞吐量的控制:
-XX:MaxGCPauseMillis=n(機關ms) 設定垃圾回收的最大停頓時間,
-XX:GCTimeRatio=n(n在0-100之間) 設定吞吐量的大小, 假設值為n, 那系統将花費不超過1/(n+1)的時間用于垃圾回收
-XX:+UseAdaptiveSizePolicy 打開自适應GC政策, 在這種模式下, 新生代的大小, eden,survivior的比例, 晉升老年代的對象年齡等參數會被自動調整,以達到堆大小, 吞吐量, 停頓時間之間的平衡點
2.3)老年代ParallelOldGC回收器
- 同新生代的ParallelGC回收器一樣, 是屬于老年代的關注吞吐量的多線程并發回收器
- 使用标記壓縮算法
-XX:+UseParallelOldGC 新生代用ParallelGC回收器, 老年代使用ParallelOldGC回收器, 是非常關注系統吞吐量的回收器組合, 适合用于對吞吐量要求較高的系統
-XX:ParallelGCThreads=n 指回ParNew回收器工作時的線程數量, cpu核數小時8時, 其值等于cpu數量, 高于8時, 可以使用公式(3+((5*CPU_count)/8))
3. CMS回收器(Concurrent Mark Sweep,并發标記清除)
3.1)老年代的并發回收器
- 是并發回收, 非獨占式的回收器, 大部分時候應用程式不會停止運作
- 針對年老代的回收器
- 使用并發标記清除算法, 是以回收後會有記憶體碎片, 可以使參數設定進行記憶體碎片的壓縮整理
- 與ParallelGC和ParallelOldGC不同, CMS主要關注系統停頓時間
主要步驟
- 初始标記
- 并發标記
- 預清理
- 重新标記
- 并發清理
- 并發重置
需要注意:初始标記與重新标記是獨占系統資源的,不能與使用者線程一起執行,而其它階段則可以與使用者線程一起執行
-XX:-CMSPrecleaningEnabled 關閉預清理, 不進行預清理, 預設在并發标記後, 會有一個預清理的操作,可減少停頓時間
-XX:+UseConcMarkSweepGC 老年代使用CMS回收器, 新生代使用ParNew回收器
-XX:ConcGCThreads=n 設定并發線程數量,
-XX:ParallelCMSThreads=n 同上, 設定并發線程數量,
-XX:CMSInitiatingOccupancyFraction=n 指定老年代回收閥值, 即當老年代記憶體使用率達到這個值時, 會執行一次CMS回收,預設值為68, 設定技巧: (Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100)>=Xmn
-XX:+UseCMSCompactAtFullCollection 開啟記憶體碎片的整理, 即當CMS垃圾回收完成後, 進行一次記憶體碎片整理, 要注意記憶體碎片的整理并不是并發進行的, 是以可能會引起程式停頓
-XX:CMSFullGCsBeforeCompation=n 用于指定進行多少次CMS回收後, 再進行一次記憶體壓縮
-XX:+CMSParallelRemarkEnabled 在使用UseParNewGC 的情況下, 盡量減少 mark 的時間
-XX:+UseCMSInitiatingOccupancyOnly 表示隻有達到閥值時才進行CMS回收
-XX:+CMSConcurrentMTEnabled 當該标志被啟用時,并發的CMS階段将以多線程執行,預設開啟
-XX:+CMSIncrementalMode 在增量模式下,CMS 收集器在并發階段,不會獨占整個周期,而會周期性的暫停,喚醒應用線程。收集器把并發階段工作,劃分為片段,安排在次級(minor) 回收之間運作。這對需要低延遲,運作在少量CPU伺服器上的應用很有用。
3.2)Class的回收(永久區的回收)
-XX:+CMSClassUnloadingEnabled 開啟回收Perm區的記憶體, 預設情況下, 是需要觸發一次FullGC
-XX:CMSInitiatingPermOccupancyFraction=n 當永久區占用率達到這個n值時,啟動CMS回收, 需上一個參數開啟的情況下使用
4. G1回收器(JDK1.7後全新的回收器, 用于取代CMS)
4.1)概述
- 獨特的垃圾回收政策, 屬于分代垃圾回收器
- 使用分區算法, 不要求eden, 年輕代或老年代的空間都連續
- 并行性:回收期間, 可由多個線程同時工作, 有效利用多核cpu資源
- 并發性:與應用程式可交替執行, 部分工作可以和應用程式同時執行
- 分代GC::分代收集器, 同時兼顧年輕代和老年代
- 空間整理:回收過程中, 會進行适當對象移動, 減少空間碎片
- 可預見性:G1可選取部分區域進行回收, 可以縮小回收範圍, 減少全局停頓
- 新生代GC
- 并發标記周期
初始标記新生代GC(此時是并行, 應用程式會暫停止) –> 根區域掃描 –> 并發标記 –> 重新标記(此時是并行, 應用程式會暫停止) –> 獨占清理(此時應用程式會暫停止) –> 并發清理
- 混合回收
這個階段即會執行正常的年輕代gc, 也會選取一些被标記的老年代區域進行回收, 同時處理新生代和年老輕
- 若需要,會進行FullGC
混合GC時發生空間不足
在新生代GC時, survivor區和老年代無法容納幸存對象時
以上兩者都會導緻一次FullGC産生
-XX:+UseG1GC 打開G1收集器開關,
-XX:MaxGCPauseMillis=n 指定目标的最大停頓時間,任何一次停頓時間超過這個值, G1就會嘗試調整新生代和老年代的比例, 調整堆大小, 調整晉升年齡
-XX:ParallelGCThreads=n 用于設定并行回收時, GC的工作線程數量
-XX:InitiatingHeapOccpancyPercent=n 指定整個堆的使用率達到多少時, 執行一次并發标記周期, 預設45, 過大會導緻并發标記周期遲遲不能啟動, 增加FullGC的可能, 過小會導緻GC頻繁, 會導緻應用程式性能有所下降
4.2)參數選項
-XX:+UseG1GC | 使用G1垃圾處理器 | |
-XX:MaxGCPauseMillis=n | 預設值:4294967295 | 設定并行收集最大暫停時間,這是一個理想目标,JVM将盡最大努力來實作它。 |
-XX:InitiatingHeapOccupancyPercent=n | 預設值:45 | 啟動一個并發垃圾收集周期所需要達到的整堆占用比例。這個比例是指整個堆的占用比例而不是某一個代(例如G1),如果這個值是0則代表‘持續做GC’。預設值是45 |
-XX:NewRatio=n | 預設值:2 | 設定年輕代和年老代的比值。例如:值為3,則表示年輕代與年老代比值為1:3,年輕代占整個年輕代年老代和的1/4。 |
-XX:SurvivorRatio=n | 預設值:8 | 年輕代中Eden區與兩個Survivor區的比值。注意Survivor區有兩個。如:3,表示Eden:Survivor=3:2,一個Survivor區占整個年輕代的1/5 |
預設值:15 | 設定垃圾最大存活閥值。如果設定為0的話,則年輕代對象不經過Survivor區,直接進入年老代。對于年老代比較多的應用,可以提高效率。如果将此值設定為一個較大值,則年輕代對象會在Survivor區進行多次複制,這樣可以增加對象再年輕代的存活時間,增加在年輕代即被回收的概論。 | |
-XX:ConcGCThreads=n | 并行垃圾收集時,使用的線程數。預設值和JVM運作的平台有關。 | |
-XX:G1ReservePercent=n | 預設值:10 | 設定保留用來做假天花闆以減少晉升(新生代對象晉升到老生代)失敗可能性的堆數目。 |
-XX:G1HeapRegionSize=n | 預設值根據堆大小而定 | 使用G1垃圾回收器,java堆被劃分成統一大小的區塊。這個選項設定每個區塊的大小。最小值是1Mb,最大值是32Mb。 |
4.3)其他GC相關的設定
4.3.1)System.gc()
1)禁用System.gc()
-XX:+DisableExplicitGC 禁止程式中調用System.gc(), 加了此參數, 程式若有調用, 傳回的空函數調用System.gc()的調用, 會使用FullGC的方式回收整個堆而會忽略CMS或G1等相關回收器
2)System.gc()使用并發回收
-XX:+ExplicitGCCinvokesConcurrent 使用并發方式處理顯示的gc, 即開啟後, System.gc()這種顯示GC才會并發的回收, (CMS, G1)
4.3.2)并行GC前額外觸發的新生代GC
1)使用并行回收器 (UseParallelGC或者UseParallelOldGC)時, 會額外先觸發一個新生代GC, 目的是盡可能減少停頓時間
2)若不需要這種特性, 可以使用以下參數去除
-XX:-ScavengeBeforeFullGC 即去除在FullGC之前的那次新生代GC, 原本預設值為true
4.3.3)對象何時進入老年代
1)當對象首次建立時, 會放在新生代的eden區, 若沒有GC的介入,會一直在eden區, GC後,是可能進入survivor區或者年老代
2)當對象年齡達到一定的大小 ,就會離開年輕代, 進入老年代, 對象進入老年代的事件稱為晉升, 而對象的年齡是由GC的次數決定的,
每一次GC,若對象沒有被回收, 則對象的年齡就會加1, 可以使用以下參數來控制新生代對象的最大年齡:
-XX:MaxTenuringThreshold=n 假設值為n , 則新生代的對象最多經曆n次GC, 就能晉升到老年代, 但這個必不是晉升的必要條件
-XX:TargetSurvivorRatio=n 用于設定Survivor區的目标使用率,即當survivor區GC後使用率超過這個值, 就可能會使用較小的年齡作為晉升年齡
3)除年齡外, 對象體積也會影響對象的晉升的, 若對象體積太大, 新生代無法容納這個對象, 則這個對象可能就會直接晉升至老年代, 可通過以下參
數使用對象直接晉升至老年代的門檻值, 機關是byte
-XX:PretenureSizeThreshold 即對象的大小大于此值, 就會繞過新生代, 直接在老年代配置設定, 此參數隻對串行回收器以及ParNew回收有效, 而對ParallelGC回收器無效
4.3.4)在TLAB上配置設定對象(Thread Local Allocation Buffer, 線程本地配置設定緩存)
TLAB是一個線程專用的記憶體配置設定區域, 虛拟機為線程配置設定空間, 針對于體積不大的對象, 會優先使用TLAB, 這個可以加速對象的配置設定, TLAB是預設開啟的, 若要關閉可以使用以下參數關閉
-XX:-UseTLAB 關閉TLAB
-XX:+UseTLAB 開啟TLAB, 預設也是開啟的
-XX:+PrintTLAB 觀察TALB的使用情況
-XX:TLABRefillWasteFraction=n 設定一個比率n, 而refill_waste的值就是(TLAB_SIZE/n), 即TLAB空間較小, 大對象無法配置設定在TLAB,是以會直接配置設定到堆上,TLAB較小也很容易裝滿, 是以當TLAB的空間不夠配置設定一個新對象, 就會考慮廢棄目前TLAB空間還是直接配置設定到堆上, 就會使用此參數進行判斷, 小于refill_waste就允許廢棄, 而建立TLAB來配置設定對象,而大于refill_waste就直接在堆上配置設定, 預設是64
-XX:+ResizeTLAB 開啟TLAB自動調整大小, 預設是開啟的, 若要關閉把+号換成-号即可
-XX:TLABSize=n 設定一個TLAB的大小, 前提先關閉TLAB的自動調整
5. 性能調優工具
5.1)jps (Java Virtual Machine Process Status Tool)
主要用來輸出JVM中運作的程序狀态資訊。文法格式如下:
jps [options] [hostid]
# hostid文法如下:
[protocol:][[//]hostname][:port][/servername]
protocol - 如果protocol及hostname都沒有指定,那表示的是與目前環境相關的本地協定,如果指定了hostname卻沒有指定protocol,那麼protocol的預設就是rmi。
hostname - 伺服器的IP或者名稱,沒有指定則表示本機。
port - 遠端rmi的端口,如果沒有指定則預設為1099。
Servername - 注冊到RMI注冊中心中的jstatd的名稱。
# 如果不指定hostid就預設為目前主機或伺服器。
# 指令行參數選項
-q 忽略輸出類名、Jar名和傳入main方法的參數
-m 輸出傳入main方法的參數
-l 輸出main類或Jar的全限名
-v 輸出傳入JVM的參數
-V 輸出通過标記的檔案傳遞給JVM的參數(.hotspotrc檔案,或者是通過參數-XX:Flags=<filename>指定的檔案)
-J 用于傳遞jvm選項到由javac調用的java加載器中,例如,“-J-Xms48m”将把啟動記憶體設定為48M,使用-J選項可以非常友善的向基于Java的開發的底層虛拟機應用程式傳遞參數。
5.2)stack(Java Stack Trace)
主要用來檢視某個Java程序内的線程堆棧資訊。文法格式如下:
jstack [option] pid
jstack [option] executable core
jstack [option] [server-id@]remote-hostname-or-ip
# 指令行參數選項說明如下:
-l 長清單,會列印出額外的鎖資訊,在發生死鎖時可以用jstack -l pid來觀察鎖持有情況
-m mixed mode,不僅會輸出Java堆棧資訊,還會輸出C/C++堆棧資訊(比如Native方法)
-F 當’jstack [-l] pid’沒有相應的時候強制列印棧資訊
-h | -help列印幫助資訊
jstack可以定位到線程堆棧,根據堆棧資訊我們可以定位到具體代碼,是以它在JVM性能調優中使用得非常多。
5.3)jmap(Java Memory Map)
jmap用來檢視堆記憶體使用狀況,一般結合jhat使用。jmap文法格式如下:(如果運作在64位JVM上,可能需要指定-J-d64指令選項參數)
jmap [option] pid
jmap [option] executable core
jmap [option] [server-id@]remote-hostname-or-ip
# 參數說明
executable 産生core dump的java可執行程式
core 将被列印資訊的core dump檔案
remote-hostname-or-ip 遠端debug服務的主機名或ip
server-id 唯一id,假如一台主機上多個遠端debug服務
pid 需要被列印配相資訊的java程序id,可以用jps查問
# 基本參數
-dump:[live,]format=b,file=<filename> 使用hprof二進制形式,輸出jvm的heap内容到檔案=. live子選項是可選的,假如指定live選項,那麼隻輸出活的對象到檔案
-finalizerinfo 列印正等候回收的對象的資訊
-heap 列印heap的概要資訊,GC使用的算法,heap的配置及wise heap的使用情況
-histo[:live] 列印每個class的執行個體數目,記憶體占用,類全名資訊. VM的内部類名字開頭會加上字首”*”. 如果live子參數加上後,隻統計活的對象數量
-permstat 列印classload和jvm heap長久層的資訊. 包含每個classloader的名字,活潑性,位址,父classloader和加載的class數量. 另外,内部String的數量和占用記憶體數也會列印出來
-F 強迫.在pid沒有相應的時候使用-dump或者-histo參數. 在這個模式下,live子參數無效
-h | -help 列印輔助資訊
-J 傳遞參數給jmap啟動的jvm
5.4)jhat(Java Heap Analysis Tool)
jhat用于對JAVA heap進行離線分析的工具,它可以對不同虛拟機中導出的heap資訊檔案進行分析
# jmap -dump:format=b,file=dumpFileName pid
jmap -dump:format=b,file=/tmp/dump.dat 21711
jhat -port 9998 /tmp/dump.dat
# 注意如果Dump檔案太大,可能需要加上-J-Xmx512m這種參數指定最大堆記憶體
# 在浏覽器中輸入主機位址:9998檢視
另外,可以使用Eclipse插件MAT(Memory Analyzer Tool)對dump檔案進行分析。
5.5)jstat(Java Virtual Machine Statistics Monitoring Tool)
Jstat用于監控基于HotSpot的JVM,對其堆的使用情況進行實時的指令行的統計,使用jstat我們可以對指定的JVM做如下監控:
類的加載及解除安裝情況
- 檢視新生代、老生代及持久代的容量及使用情況
- 檢視新生代、老生代及持久代的垃圾收集情況,包括垃圾回收的次數及垃圾回收所占用的時間
- 檢視新生代中Eden區及Survior區中容量及配置設定情況等
文法:
jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]
generalOption - 單個的常用的指令行選項,如-help, -options, 或 -version。
outputOptions -一個或多個輸出選項,由單個的statOption選項組成,可以和-t, -h, and -J等選項配合使用。
statOption 根據jstat統計的次元不同,可以使用如下表中的選項進行不同次元的統計,不同的作業系統支援的選項可能會不一樣,可以通過-options選項,檢視不同作業系統所支援選項
-h n 用于指定每隔幾行就輸出列頭,如果不指定,預設是隻在第一行出現列頭。
-J javaOption 用于将給定的javaOption傳給java應用程式加載器,例如,“-J-Xms48m”将把啟動記憶體設定為48M
-t n 用于在輸出内容的第一列顯示時間戳,這個時間戳代表的時JVM開始啟動到現在的時間
vmid VM的程序号,即目前運作的java程序号
interval 間隔時間,機關可以是秒或者毫秒,通過指定s或ms确定,預設機關為毫秒
count 列印次數,如果預設則列印無數次
===統計次元與輸出===
1)class 用于檢視類加載情況的統計

2)compiler 用于檢視HotSpot中即時編譯器編譯情況的統計
3)gc 用于檢視JVM中堆的垃圾收集情況的統計
4)gccapacity 用于檢視新生代、老生代及持久代的存儲容量情況
5)gccause 用于檢視垃圾收集的統計情況(這個和-gcutil選項一樣),如果有發生垃圾收集,它還會顯示最後一次及目前正在發生垃圾收集的原因。
6)gcnew 用于檢視新生代垃圾收集的情況
7)gcnewcapacity 用于檢視新生代的存儲容量情況
8)gcold 用于檢視老生代及持久代發生GC的情況
9)gcoldcapacity 用于檢視老生代的容量
10)gcpermcapacity 用于檢視持久代的容量
11)gcutil 用于檢視新生代、老生代及持代垃圾收集的情況
12)printcompilation HotSpot編譯方法的統計
示例
jstat -gc 1618 250 4
5.6)jvisualvm(Java Virtual Machine Monitoring, Troubleshooting, and Profiling Tool)
jvisualvm同jconsole都是一個基于圖形化界面的、可以檢視本地及遠端的JAVA GUI監控工具,Jvisualvm同jconsole的使用方式一樣,直接在指令行打入Jvisualvm即可啟動,不過Jvisualvm相比,界面更美觀一些,資料更實時。
5.7)jconsole
一個java GUI監視工具,可以以圖表化的形式顯示各種資料。并可通過遠端連接配接監視遠端的伺服器VM。用java寫的GUI程式,用來監控VM,并可監控遠端的VM,非常易用,而且功能非常強。指令行裡打 jconsole,選則程序就可以了。
需要注意:在運作jconsole之前,必須要先設定環境變量DISPLAY,否則會報錯誤,Linux下設定環境變量如下:
export DISPLAY=:0.0
5.8)jprofile
JProfiler是一個需要商業授權的全功能的Java剖析工具(profiler),專用于分析J2SE和J2EE應用程式。
它把CPU、執行緒和記憶體的剖析組合在一個強大的應用中。JProfiler可提供許多IDE整合和應用伺服器整合用途。JProfiler直覺式的GUI讓你可以找到效能瓶頸、抓出記憶體漏失(memory leaks)、并解決執行緒的問題。它讓你得以對heap walker作資源回收器的root analysis,可以輕易找出記憶體漏失;heap快照(snapshot)模式讓未被參照(reference)的對象、稍微被參照的對象、或在終結(finalization)隊列的對象都會被移除;整合精靈以便剖析浏覽器的Java外挂功能。
5.9)jca
Java線程分析工具,專業的線程分析工具相容sun/oracle JDK dump線程堆,圖形化顯示線程概括資訊,非常容易的定位問題。
jca是一個類工具 啟動方法
java -jar jca433.jar
5.10)jinfo指令 (Java Configuration Info)
jinfo可以輸出并修改運作時的java 程序的opts。用處比較簡單,用于輸出JAVA系統參數及指令行參數。用法是jinfo -opt pid 如:檢視2788的MaxPerm大小可以用 jinfo -flag MaxPermSize 2788。
5.11)Jdb指令 (The Java Debugger)
用來對core檔案和正在運作的Java程序進行實時地調試,裡面包含了豐富的指令幫助您進行調試。
5.12)Jstatd指令 (Java Statistics Monitoring Daemon)
jstatd是一個基于RMI(Remove Method Invocation)的服務程式,它用于監控基于HotSpot的JVM中資源的建立及銷毀,并且提供了一個遠端接口允許遠端的監控工具連接配接到本地的JVM執行指令。
jstatd是基于RMI的,是以在運作jstatd的伺服器上必須存在RMI注冊中心,如果沒有通過選項”-p port”指定要連接配接的端口,jstatd會嘗試連接配接RMI注冊中心的預設端口。後面會談到如何連接配接到一個預設的RMI内部注冊中心,如何禁止預設的RMI内部注冊中心的建立,以及如何啟動一個外部注冊中心。
參數選項
-nr 如果RMI注冊中心沒有找到,不會建立一個内部的RMI注冊中心。
-p port RMI注冊中心的端口号,預設為1099。
-n rminame 預設為JStatRemoteHost;如果同一台主機上同時運作了多個jstatd服務,rminame可以用于唯一确定一個jstatd服務;這裡需要注意一下,如果開啟了這個選項,那麼監控用戶端遠端連接配接時,必須同時指定hostid及vmid,才可以唯一确定要連接配接的服務,這個可以參看jps章節中列出遠端伺服器上Java程序的示例。
-J 用于傳遞jvm選項到由javac調用的java加載器中,例如,“-J-Xms48m”将把啟動記憶體設定為48M,使用-J選項可以非常友善的向基于Java的開發的底層虛拟機應用程式傳遞參數。
安全性
jstatd服務隻能監視具有适當的本地通路權限的JVM,是以jstatd程序與被監控的JVM必須運作在相同的使用者權限中。但是有一些特殊的使用者權限,如基于UNIX(TM)為系統的root使用者,它有權限通路系統中所有JVM的資源,如果jstatd程序運作在這種權限中,那麼它可以監視系統中的所有JVM,但是這也帶來了額外的安全問題。
# 使用内部RMI注冊中心(預設端口是1099),啟動jstatd
jstatd -J-Djava.security.policy=jstatd.all.policy
# 使用外部的RMI注冊中心,啟動jstatd
rmiregistry&jstatd -J-Djava.security.policy=all.policy
# 外部的RMI注冊中心來啟動jstatd,此注冊中心的端口為2020
rmiregistry 2020&jstatd -J-Djava.security.policy=all.policy -p 2020
# 外部的RMI注冊中心來啟動jstatd,此注冊中心的端口為2020,并且綁定到RMI注冊中心的名為AlternateJstatdServerName
rmiregistry 2020&jstatd -J-Djava.security.policy=all.policy -p 2020 -n AlternateJstatdServerName
# 禁止内部RMI注冊中心的建立
jstatd -J-Djava.security.policy=all.policy -nr
# 開啟RMI日記記錄,jstatd運作在開啟了日志記錄功能的RMI注冊中
jstatd -J-Djava.security.policy=all.policy -J-Djava.rmi.server.logCalls=true
5.13)httpwatch
網頁資料分析工具,對用戶端到伺服器端的請求,響應資料有效的監控分析。
6. 生産環境示例
6.1)Tomcat7
catalina.sh(隻運作一個Tomcat)
# 8G記憶體
JAVA_OPTS="
-Dfile.encoding=UTF-8
-server
-Djava.awt.headless=true
-Xms6144m
-Xmx6144m
-XX:NewSize=1024m
-XX:MaxNewSize=2048m
-XX:PermSize=512m
-XX:MaxPermSize=512m
-XX:MaxTenuringThreshold=15
-XX:NewRatio=2
-XX:+AggressiveOpts
-XX:+UseBiasedLocking
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled
-XX:LargePageSizeInBytes=128m
-XX:+UseFastAccessorMethods
-XX:+UseCMSInitiatingOccupancyOnly
-XX:+DisableExplicitGC"
# 16G記憶體(垃圾回收略)
JAVA_OPTS="
-Dfile.encoding=UTF-8
-server
-Xms13312m
-Xmx13312m
-XX:NewSize=3072m
-XX:MaxNewSize=4096m
-XX:PermSize=512m
-XX:MaxPermSize=512m
-XX:MaxTenuringThreshold=10
-XX:NewRatio=2
-XX:+DisableExplicitGC"
# 32G記憶體(垃圾回收略)
JAVA_OPTS="
-Dfile.encoding=UTF-8
-server
-Xms29696m
-Xmx29696m
-XX:NewSize=6144m
-XX:MaxNewSize=9216m
-XX:PermSize=1024m
-XX:MaxPermSize=1024m
-XX:MaxTenuringThreshold=10
-XX:NewRatio=2
-XX:+DisableExplicitGC"
6.2)Hadoop
建議Hadoop程序的GC參數加上如下選項,很多商業版都預設加上了,這對JDK性能提升有很大幫助
-XX:CMSInitiatingOccupancyFraction=70
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseConcMarkSweepGC
-XX:-CMSConcurrentMTEnabled
-XX:+CMSIncrementalMode
-Djava.net.preferIPv4Stack=true
7. 參考
JDK8中JVM堆記憶體劃分
JDK8引進的JVM參數變化記錄
JVM 不穩定參數
java 8 JVM性能優化
Java性能優化攻略詳解
Jvm垃圾回收器詳細
JVM性能調優監控工具jps、jstack、jmap、jhat、jstat、hprof使用詳解
jps指令 (Java Virtual Machine Process Status Tool)
Could not create the Java virtual machine
一般原因如下:
1)執行程式裡的JAVA路徑不對造成的!通過"echo $JAVA_HOME"查找出JAVA路徑,然後更新程式中的JAVA路徑配置即可。
2)JVM參數不對造成(可能是stack size太小)。修改JVM_OPTIONS配置裡的JVM參數值即可。
3)jdk版本不相容導緻。調整jdk版本(比如jdk版本過低,調整為高版本的jdk)即可。
*************** 當你發現自己的才華撐不起野心時,就請安靜下來學習吧!***************