JAVA線上CPU/內(nèi)存故障排查命令大全,讓你迅速成為線上故障排查高手

一、 檢查啟JAVA應(yīng)用JVM參數(shù)配置

CPU占用高排查:首先確認異常的進程:
一般CPU100%瘋狂GC,都是死循環(huán)的鍋,那怎么排查呢?
1.先進服務(wù)器,用top -c 命令找出當前進程的運行列表
2.按一下 P 可以按照CPU使用率進行排序
3.顯示Java進程 PID 為 2896 的java進程消耗最高
4.然后我們需要根據(jù)PID 查出CPU里面消耗最高的進程
5.使用命令 top -Hp PID 找出這個進程下面的線程,繼續(xù)按 P 排序
6.然后看可以看到 TID = 7051 占用CPU消耗最高(注意這個時候已經(jīng)是線程ID)
①按進程的CPU使用率排序
②運行top命令后,鍵入大寫P
有兩種途徑:
a) 打開大寫鍵盤的情況下,直接按P鍵
b) 未打開大寫鍵盤的情況下,Shift+P鍵

話外音:內(nèi)存占用高,如何查看 ?

①按進程的內(nèi)存使用率排序
②運行top命令后,鍵入大寫M
有兩種途徑:
a) 打開大寫鍵盤的情況下,直接按M鍵
b) 未打開大寫鍵盤的情況下,Shift+M鍵
按Enter鍵可以查看,及時的情況
TOP交互命令如下
c: 顯示完整的命令
d: 更改刷新頻率
f: 增加或減少要顯示的列(選中的會變成大寫并加*號)
F: 選擇排序的列
h: 顯示幫助畫面
H: 顯示線程
i: 忽略閑置和僵死進程
k: 通過給予一個PID和一個signal來終止一個進程。(默認signal為15。在安全模式中此命令被屏蔽)
l:  顯示平均負載以及啟動時間(即顯示影藏第一行)
m: 顯示內(nèi)存信息
M: 根據(jù)內(nèi)存資源使用大小進行排序
N: 按PID由高到低排列
o: 改變列顯示的順序
O: 選擇排序的列,與F完全相同
P: 根據(jù)CPU資源使用大小進行排序
q: 退出top命令
r: 修改進程的nice值(優(yōu)先級)。優(yōu)先級默認為10,正值使優(yōu)先級降低,反之則提高的優(yōu)先級
s: 設(shè)置刷新頻率(默認單位為秒,如有小數(shù)則換算成ms)。默認值是5s,輸入0值則系統(tǒng)將不斷刷新
S: 累計模式(把已完成或退出的子進程占用的CPU時間累計到父進程的MITE+ )
T: 根據(jù)進程使用CPU的累積時間排序
t: 顯示進程和CPU狀態(tài)信息(即顯示影藏CPU行)
u: 指定用戶進程
W: 將當前設(shè)置寫入~/.toprc文件,下次啟動自動調(diào)用toprc文件的設(shè)置
<: 向前翻頁
>: 向后翻頁
?: 顯示幫助畫面
1(數(shù)字1): 顯示每個CPU的詳細情況
將JAVA線程運行情況dump到指定路徑,通過命令行或者MAT輔助分析如下:
①使用 pringf "%x\n" 2854(注意: 2854為占用高的線程ID)
轉(zhuǎn)成十六進制,轉(zhuǎn)換結(jié)果:b26
②接下來就需要導(dǎo)出我們的進程快照了,看看這個線程做了啥
③ jstack -l 2609 > ./err.log
再用grep查看一下線程在文件里做了啥/或者使用MAT分析dump文件(更加方便)
④cat err.log| grep 'b26' -C 10

注意:提前獲取Application應(yīng)用的啟動參數(shù),方便定位和排查問題

ps aux | grep app.jar 輸出JVM的相關(guān)參數(shù)(經(jīng)常使用)

##通過以下命令查看JVM的啟動參數(shù):
ps aux | grep  app.jar 輸出JVM的相關(guān)參數(shù)
jps -lv   輸出啟動類名與啟動時 jvm 參數(shù),可以方便的看到各個 tomcat 的自定義參數(shù)配置
jps -lv | grep  app.jar  在上述基礎(chǔ)上過濾出自己想要查看的項目的信息

jinfo pid  顯示 jvm 系統(tǒng)屬性與 vm 參數(shù)信息
jinfo -flags pid 顯示 jvm vm 參數(shù)信息,如最大最小堆,默認堆,垃圾收集器參數(shù)等
jinfo -sysprops pid  顯示 jvm 系統(tǒng)屬性
jinfo -flag  顯示特定 vm 參數(shù)值,例如 jinfo -flag MaxHeapSize pid 輸出 pid 的最大堆內(nèi)存

二、jstat (jvm statistics monitoring tool) 收集運行數(shù)據(jù)(堆棧排查相關(guān))

1、語法格式

jstat -gc pid 1s 20 (經(jīng)常使用)

jstat  [option pid [interval[s|ms] [count]]]
說明: interval 表示循環(huán)時間間隔,默認單位為 ms,可以在直接使用 s/ms 指定單位
如 60ms/1s, count 表示輸出幾次 例如下:
jstat -gc pid 1s 20 : 每 1s 查詢一次 gc 情況,查詢 20 次

2、option 詳解(主要分三類:類裝載、垃圾收集、運行期編譯狀況)

3.查看 GC 情況

jstat -gc pid (經(jīng)常使用)


4、查看 GC 情況,以百分比顯示

jstat -gcutil pid (經(jīng)常使用)

5、查看新生代 GC 情況
jstat -gcnew pid

6、查看老年代 GC 情況

jstat -gcold pid

7、查看各空間容量

jstat -gccapacity pid

8、查看編譯情況
jstat -compiler pid

三、jmap (memory map for java) 虛擬機堆快照工具

1、常用用法

jmap -heap pid (經(jīng)常使用)

使用實例 jmap -heap 28076| head -n60

jmap -dump:format=b,file=/temp/filename.hprof pid (經(jīng)常使用)

轉(zhuǎn)儲堆快照,生成 hprof 文件到指定路徑**

jmap -histo pid | more (經(jīng)常使用)

列出當前 heap 中對象狀況,附字節(jié)碼與 java 對象映射表
(1)jmap -heap pid 查看JVM空間總體使用情況
(2)jmap -histo pid |more 查看類的實例數(shù)和內(nèi)存量
(3)jmap -histo:live pid |more 查看所有活著的實例數(shù)量。
(4)jmap -dump:format=b,file=dump_tomcat.dat pid 將內(nèi)存使用情況dump到文件中

四、jstack (stack trace for java) 虛擬機線程快照工具(主要獲取運行線程相關(guān))

jstack -h查看stack的命令提示

jstack [-l] <pid>
    (to connect to running process)
jstack -F [-m] [-l] <pid>
    (to connect to a hung process)
jstack [-m] [-l] <executable> <core>
    (to connect to a core file)
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
    (to connect to a remote debug server)

jstack pid > ./a.log (經(jīng)常使用)

將生成的運行線程的相關(guān)信息輸出到a.log日志中,下載查看

查看線程棧執(zhí)行情況/會顯示所有線程的各種信息,可以用來排查死鎖,或線程長時間停滯的問題

①可以通過MAT工具進行分析

5、Tomcat內(nèi)存設(shè)置

windows下在catalina.bat的第一行增加:
Java代碼 :set JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m
Linux下在catalina.sh的第一行增加:
Java代碼 :JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m

實例+詳解

設(shè)置Tomcat啟動的初始內(nèi)存其初始空間(即-Xms)是物理內(nèi)存的1/64,最大空間(-Xmx)是物理內(nèi)存的1/4。
可以利用JVM提供的-Xmn -Xms -Xmx等選項可進行設(shè)置

實例,以下給出1G內(nèi)存環(huán)境下Java jvm
的參數(shù)設(shè)置參考:

JAVA_OPTS=”-server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true “

JAVA_OPTS=”-server -Xms768m -Xmx768m -XX:PermSize=128m -XX:MaxPermSize=256m -XX: NewSize=192m -XX:MaxNewSize=384m”

CATALINA_OPTS=”-server -Xms768m -Xmx768m -XX:PermSize=128m -XX:MaxPermSize=256m -XX:NewSize=192m -XX:MaxNewSize=384m”

linux

在/usr/local/apache-tomcat-5.5.23/bin 目錄下的catalina.sh添加:

JAVA_OPTS=’-Xms512m -Xmx1024m’要加“m”說明是MB,否則就是KB了,在啟動tomcat時會 報內(nèi)存不足。

-Xms:初始值-Xmx:最大值-Xmn:最小值

Windows:

在catalina.bat最前面加入set JAVA_OPTS=-Xms128m -Xmx350m

如果用startup.bat啟動tomcat,OK設(shè)置生效.夠成功的分配200M內(nèi)存.

但是如果不是執(zhí)行startup.bat啟動tomcat而是利用windows的系統(tǒng)服務(wù)啟動tomcat服務(wù),上面的設(shè)置就不生效了,就是說set JAVA_OPTS=-Xms128m -Xmx350m 沒起作用.上面分配200M內(nèi)存就OOM了..

windows服務(wù)執(zhí)行的是bin\tomcat.exe.他讀取注冊表中的值,而不是catalina.bat的設(shè)置.

解決辦法:

修改注冊表HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Tomcat Service Manager\Tomcat5\Parameters\JavaOptions

原值為-Dcatalina.home=”C:\ApacheGroup\Tomcat 5.0″-Djava.endorsed.dirs=”C:\ApacheGroup\Tomcat 5.0\common\endorsed”-Xrs加入 -Xms300m -Xmx350m

重起tomcat服務(wù),設(shè)置生效

**Tomcat 的JVM 內(nèi)存溢出問題的解決關(guān)鍵字: tomcat 的jvm 內(nèi)存溢出問題的解決 **

最近在熟悉一個開發(fā)了有幾年的項目,需要把數(shù)據(jù)庫MySQL移植到Oracle,首先把jdbc的連接指向mysql,打包放到tomcat里面,可以跑起來,沒有問題,可是當把jdbc連接指向oracle的時候,tomcat就連續(xù)拋java.lang.OutOfMemoryError的錯誤,上網(wǎng)google了一下,了解了一下tomcat的運行機制,也解決了問題,share出來,以備查。

1、首先是:java.lang.OutOfMemoryError: java heap
space 解釋:

Heap size 設(shè)置 JVM堆的設(shè)置是指java程序運行過程中JVM可以調(diào)配使用的內(nèi)存空間的設(shè)置.JVM在啟動的時候會自動設(shè)置Heap size的值,其初始空間(即-Xms)是物理內(nèi)存的1/64,最大空間(-Xmx)是物理內(nèi)存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等選項可進行設(shè)置。Heap size 的大小是Young Generation 和Tenured Generaion
之和。

提示:在JVM中如果98%的時間是用于GC且可用的Heap size 不足2%的時候?qū)伋龃水惓P畔ⅰ?/p>

提示:Heap Size 最大不要超過可用物理內(nèi)存的80%,一般的要將-Xms和-Xmx選項設(shè)置為相同,而-Xmn為1/4的-Xmx值。

解決方法:

手動設(shè)置Heap size 修改TOMCAT_HOME/bin/catalina.bat,在“echo “Using CATALINA_BASE: $CATALINA_BASE””上面加入以下行:

Java代碼 set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m

或修改catalina.sh 在“echo “Using CATALINA_BASE: CATALINA_BASE””上面加入以下行: JAVA_OPTS=”JAVA_OPTS -server -Xms800m -Xmx800m -XX:MaxNewSize=256m”

2、其次是:java.lang.OutOfMemoryError: PermGen space 原因:

PermGen space的全稱是Permanent Generation space,是指內(nèi)存的永久保存區(qū)域,這塊內(nèi)存主要是被JVM存放Class和Meta信息的,Class在被Loader時就會被放到PermGen space中,它和存放類實例(Instance)的Heap區(qū)域不同,GC(Garbage Collection)不會在主程序運行期對PermGen space進行清理,所以如果你的應(yīng)用中有很CLASS的話,就很可能出現(xiàn)PermGen
space錯誤,這種錯誤常見在web服務(wù)器對JSP進行pre compile的時候。如果你的WEB APP下都用了大量的第三方j(luò)ar, 其大小超過了jvm默認的大小(4M)那么就會產(chǎn)生此錯誤信息了。

解決方法:

1. 手動設(shè)置MaxPermSize大小 修改TOMCAT_HOME/bin/catalina.bat(Linux下為catalina.sh),在Java代碼 “echo “Using CATALINA_BASE: $CATALINA_BASE””上面加入以下行: set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=128M -XX:MaxPermSize=512m

catalina.sh下為: Java代碼 JAVA_OPTS=”$JAVA_OPTS -server -XX:PermSize=128M -XX:MaxPermSize=512m”

下面給出各種可以用戶設(shè)置堆大小的命令行參數(shù)。注釋列提供了一些設(shè)置參數(shù)的初級或高級建議。此外,后面還會給出更多的詳細建議。

| 參數(shù) | 描述 | 注釋 |
| -Xms<size> | 設(shè)置堆的最小值 | 在生產(chǎn)階段,最小和最大堆值設(shè)置為相同的值 |
| -Xmx<size> | 設(shè)置堆的最大值 | |
| -XX:NewSize=<size> | 設(shè)置年輕代的最小值 | 在生產(chǎn)階段,最小和最大年輕代的值設(shè)為相同的值 |
| -XX:MaxNewSize=<size> | 設(shè)置年輕代的最大值 | |
| -XX:NewRatio=<number> | 設(shè)置年輕代和年老代的大小比例。例如,數(shù)值為2時
年老代將會是年輕代大小的2倍。 | 使用NewSize/MaxNewSize參數(shù)或NewRatio參數(shù),但不要兩個參數(shù)都使用 |
| -XX:SurvivorRatio=<number> | 設(shè)置eden space和剩余空間的大小比例。例如,剩余空間比例為8時,eden space是任一剩余空間大小的8倍。 | 基于年輕代大小改變比例。比例值為8適用于
小的年輕代(如10M),32適用于比較大的年輕代(如100M)。 |
| -XX:MaxTenuringThreshold=<number> | 表示一個對象在被自動放置于年老代之前必須存活的次要回收的次數(shù) | 一般應(yīng)該使用的值為32 |
| -XX:MaxPermSizse=<size> | 設(shè)置永久代的大小 | 在用完空間后在設(shè)置永久代 |
| -XX:+UserTLAB | 在eden space里給應(yīng)用程序的每一個線程提供它自己的分配區(qū)域(線程本地分配塊TLAB)。注意它是一個布爾型選項,
用plus(+)可以啟動它,用minus(-)(-XX:-UseTLAB)可以禁用它 | 主要對多處理器系統(tǒng)有利 |
| -XX:TLABSize=<size> | 每一個TLAB的大小 | 確保年輕代空間足夠為應(yīng)用程序里的每一個線程保存所有的TLAB。應(yīng)該分別使用64KB、128KB和256KB進行嘗試 |

注意:1.<size>是一個表示字節(jié)數(shù)量的浮點數(shù),在其后面加上K、M、G后綴分別代表KB、MB、GB。

        2.<number>是一個浮點數(shù)。
  1. 堆大小設(shè)置 JVM 中最大堆大小有三方面限制:相關(guān)操作系統(tǒng)的數(shù)據(jù)模型(32-bt還是64-bit)限制;系統(tǒng)的可用虛擬內(nèi)存限制;系統(tǒng)的可用物理內(nèi)存限制。32位系統(tǒng)下,一般限制在1.5G~2G;64為操作系統(tǒng)對內(nèi)存無限制。我在Windows Server 2003 系統(tǒng),3.5G物理內(nèi)存,JDK5.0下測試,最大可設(shè)置為1478m。
    典型設(shè)置:
    • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k
      –****Xmx3550m
      :設(shè)置JVM最大可用內(nèi)存為3550M。
      -Xms3550m:設(shè)置JVM促使內(nèi)存為3550m。此值可以設(shè)置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內(nèi)存。
      -Xmn2g:設(shè)置年輕代大小為2G。整個JVM內(nèi)存大小=年輕代大小 + 年老代大小 + 持久代大小。持久代一般固定大小為64m,所以增大年輕代后,將會減小年老代大小。此值對系統(tǒng)性能影響較大,Sun官方推薦配置為整個堆的3/8。
      -Xss128k:設(shè)置每個線程的堆棧大小。JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。更具應(yīng)用的線程所需內(nèi)存大小進行調(diào)整。在相同物理內(nèi)存下,減小這個值能生成更多的線程。但是操作系統(tǒng)對一個進程內(nèi)的線程數(shù)還是有限制的,不能無限生成,經(jīng)驗值在3000~5000左右。
    • java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0
      -XX:NewRatio=4
      :設(shè)置年輕代(包括Eden和兩個Survivor區(qū))與年老代的比值(除去持久代)。設(shè)置為4,則年輕代與年老代所占比值為1:4,年輕代占整個堆棧的1/5
      -XX:SurvivorRatio=4:設(shè)置年輕代中Eden區(qū)與Survivor區(qū)的大小比值。設(shè)置為4,則兩個Survivor區(qū)與一個Eden區(qū)的比值為2:4,一個Survivor區(qū)占整個年輕代的1/6
      -XX:MaxPermSize=16m:設(shè)置持久代大小為16m。
      -XX:MaxTenuringThreshold=0:設(shè)置垃圾最大年齡。如果設(shè)置為0的話,則年輕代對象不經(jīng)過Survivor區(qū),直接進入年老代。對于年老代比較多的應(yīng)用,可以提高效率。如果將此值設(shè)置為一個較大值,則年輕代對象會在Survivor區(qū)進行多次復(fù)制,這樣可以增加對象再年輕代的存活時間,增加在年輕代即被回收的概論。
  2. 回收器選擇 JVM給了三種選擇:串行收集器、并行收集器、并發(fā)收集器,但是串行收集器只適用于小數(shù)據(jù)量的情況,所以這里的選擇主要針對并行收集器和并發(fā)收集器。默認情況下,JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在啟動時加入相應(yīng)參數(shù)。JDK5.0以后,JVM會根據(jù)當前系統(tǒng)配置進行判斷。
    1. 吞吐量優(yōu)先的并行收集器
      如上文所述,并行收集器主要以到達一定的吞吐量為目標,適用于科學(xué)技術(shù)和后臺處理等。
      典型配置
      • java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
        -XX:+UseParallelGC
        :選擇垃圾收集器為并行收集器。此配置僅對年輕代有效。即上述配置下,年輕代使用并發(fā)收集,而年老代仍舊使用串行收集。 -XX:ParallelGCThreads=20:配置并行收集器的線程數(shù),即:同時多少個線程一起進行垃圾回收。此值最好配置與處理器數(shù)目相等。
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC -XX:+UseParallelOldGC:配置年老代垃圾收集方式為并行收集。JDK6.0支持對年老代并行收集。
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100 -XX:MaxGCPauseMillis=100****:設(shè)置每次年輕代垃圾回收的最長時間,如果無法滿足此時間,JVM會自動調(diào)整年輕代大小,以滿足此值。
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100 -XX:+UseAdaptiveSizePolicy
        -XX:+UseAdaptiveSizePolicy
        :設(shè)置此選項后,并行收集器會自動選擇年輕代區(qū)大小和相應(yīng)的Survivor區(qū)比例,以達到目標系統(tǒng)規(guī)定的最低相應(yīng)時間或者收集頻率等,此值建議使用并行收集器時,一直打開。
    2. 響應(yīng)時間優(yōu)先的并發(fā)收集器
      如上文所述,并發(fā)收集器主要是保證系統(tǒng)的響應(yīng)時間,減少垃圾收集時的停頓時間。適用于應(yīng)用服務(wù)器、電信領(lǐng)域等。
      典型配置
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+UseConcMarkSweepGC:設(shè)置年老代為并發(fā)收集。測試中配置這個以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此時年輕代大小最好用-Xmn設(shè)置。
        -XX:+UseParNewGC:設(shè)置年輕代為并行收集??膳cCMS收集同時使用。JDK5.0以上,JVM會根據(jù)系統(tǒng)配置自行設(shè)置,所以無需再設(shè)置此值。
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection
        -XX:CMSFullGCsBeforeCompaction:由于并發(fā)收集器不對內(nèi)存空間進行壓縮、整理,所以運行一段時間以后會產(chǎn)生“碎片”,使得運行效率降低。此值設(shè)置運行多少次GC以后對內(nèi)存空間進行壓縮、整理。 -XX:+UseCMSCompactAtFullCollection:打開對年老代的壓縮??赡軙绊懶阅?,但是可以消除碎片
  3. 輔助信息 JVM提供了大量命令行參數(shù),打印信息,供調(diào)試使用。主要有以下一些:
    • -XX:+PrintGC 輸出形式:[GC 118250K->113543K(130112K), 0.0094143 secs]

      ** [Full GC 121376K->10414K(130112K), 0.0650971 secs]**

    • -XX:+PrintGCDetails 輸出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs]

      ** [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]**

    • -XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可與上面兩個混合使用
      輸出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]

    • -XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中斷的執(zhí)行時間??膳c上面混合使用
      輸出形式:Application time: 0.5291524 seconds

    • -XX:+PrintGCApplicationStoppedTime:打印垃圾回收期間程序暫停的時間??膳c上面混合使用
      輸出形式:Total time for which application threads were stopped: 0.0468229 seconds

    • -XX:PrintHeapAtGC:打印GC前后的詳細堆棧信息
      輸出形式:
      34.702: [GC {Heap before gc invocations=7:
      def new generation total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000)
      eden space 49152K, 99% used [0x1ebd0000, 0x21bce430, 0x21bd0000)
      from space 6144K, 55% used [0x221d0000, 0x22527e10, 0x227d0000)
      to space 6144K, 0% used [0x21bd0000, 0x21bd0000, 0x221d0000)
      tenured generation total 69632K, used 2696K [0x227d0000, 0x26bd0000, 0x26bd0000)
      the space 69632K, 3% used [0x227d0000, 0x22a720f8, 0x22a72200, 0x26bd0000)
      compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
      the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
      ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
      rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
      34.735: [DefNew: 52568K->3433K(55296K), 0.0072126 secs] 55264K->6615K(124928K)Heap after gc invocations=8: def new generation total 55296K, used 3433K [0x1ebd0000, 0x227d0000, 0x227d0000)
      eden space 49152K, 0% used [0x1ebd0000, 0x1ebd0000, 0x21bd0000)
      from space 6144K, 55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000)
      to space 6144K, 0% used [0x221d0000, 0x221d0000, 0x227d0000)
      tenured generation total 69632K, used 3182K [0x227d0000, 0x26bd0000, 0x26bd0000)
      **the space 69632K, 4% used **[0x227d0000, 0x22aeb958, 0x22aeba00, 0x26bd0000)
      compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
      the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
      ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
      rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
      }
      , 0.0757599 secs]

    • -Xloggc:filename:與上面幾個配合使用,把相關(guān)日志信息記錄到文件以便分析。

  4. 常見配置匯總
    1. 堆設(shè)置
      • -Xms:初始堆大小
      • -Xmx:最大堆大小
      • -XX:NewSize=n:設(shè)置年輕代大小
      • -XX:NewRatio=n:設(shè)置年輕代和年老代的比值。如:為3,表示年輕代與年老代比值為1:3,年輕代占整個年輕代年老代和的1/4
      • -XX:SurvivorRatio=n:年輕代中Eden區(qū)與兩個Survivor區(qū)的比值。注意Survivor區(qū)有兩個。如:3,表示Eden:Survivor=3:2,一個Survivor區(qū)占整個年輕代的1/5
      • -XX:MaxPermSize=n:設(shè)置持久代大小
    2. 收集器設(shè)置
      • -XX:+UseSerialGC:設(shè)置串行收集器
      • -XX:+UseParallelGC:設(shè)置并行收集器
      • -XX:+UseParalledlOldGC:設(shè)置并行年老代收集器
      • -XX:+UseConcMarkSweepGC:設(shè)置并發(fā)收集器
    3. 垃圾回收統(tǒng)計信息
      • -XX:+PrintGC
      • -XX:+PrintGCDetails
      • -XX:+PrintGCTimeStamps
      • -Xloggc:filename
    4. 并行收集器設(shè)置
      • -XX:ParallelGCThreads=n:設(shè)置并行收集器收集時使用的CPU數(shù)。并行收集線程數(shù)。
      • -XX:MaxGCPauseMillis=n:設(shè)置并行收集最大暫停時間
      • -XX:GCTimeRatio=n:設(shè)置垃圾回收時間占程序運行時間的百分比。公式為1/(1+n)
    5. 并發(fā)收集器設(shè)置
      • -XX:+CMSIncrementalMode:設(shè)置為增量模式。適用于單CPU情況。
      • -XX:ParallelGCThreads=n:設(shè)置并發(fā)收集器年輕代收集方式為并行收集時,使用的CPU數(shù)。并行收集線程數(shù)。

四、調(diào)優(yōu)總結(jié)

  1. 年輕代大小選擇
    • 響應(yīng)時間優(yōu)先的應(yīng)用盡可能設(shè)大,直到接近系統(tǒng)的最低響應(yīng)時間限制(根據(jù)實際情況選擇)。在此種情況下,年輕代收集發(fā)生的頻率也是最小的。同時,減少到達年老代的對象。
    • 吞吐量優(yōu)先的應(yīng)用:盡可能的設(shè)置大,可能到達Gbit的程度。因為對響應(yīng)時間沒有要求,垃圾收集可以并行進行,一般適合8CPU以上的應(yīng)用。
  2. 年老代大小選擇
    • 響應(yīng)時間優(yōu)先的應(yīng)用:年老代使用并發(fā)收集器,所以其大小需要小心設(shè)置,一般要考慮并發(fā)會話率會話持續(xù)時間等一些參數(shù)。如果堆設(shè)置小了,可以會造成內(nèi)存碎片、高回收頻率以及應(yīng)用暫停而使用傳統(tǒng)的標記清除方式;如果堆大了,則需要較長的收集時間。最優(yōu)化的方案,一般需要參考以下數(shù)據(jù)獲得:

      • 并發(fā)垃圾收集信息
      • 持久代并發(fā)收集次數(shù)
      • 傳統(tǒng)GC信息
      • 花在年輕代和年老代回收上的時間比例

      減少年輕代和年老代花費的時間,一般會提高應(yīng)用的效率

    • 吞吐量優(yōu)先的應(yīng)用:一般吞吐量優(yōu)先的應(yīng)用都有一個很大的年輕代和一個較小的年老代。原因是,這樣可以盡可能回收掉大部分短期對象,減少中期的對象,而年老代盡存放長期存活對象。

  3. 較小堆引起的碎片問題 因為年老代的并發(fā)收集器使用標記、清除算法,所以不會對堆進行壓縮。當收集器回收時,他會把相鄰的空間進行合并,這樣可以分配給較大的對象。但是,當堆空間較小時,運行一段時間以后,就會出現(xiàn)“碎片”,如果并發(fā)收集器找不到足夠的空間,那么并發(fā)收集器將會停止,然后使用傳統(tǒng)的標記、清除方式進行回收。如果出現(xiàn)“碎片”,可能需要進行如下配置:
    • -XX:+UseCMSCompactAtFullCollection:使用并發(fā)收集器時,開啟對年老代的壓縮。
    • -XX:CMSFullGCsBeforeCompaction=0:上面配置開啟的情況下,這里設(shè)置多少次Full GC后,對年老代進行壓縮

1.在eclipse設(shè)置JVM參數(shù)
打開eclipse-窗口-首選項-Java-已安裝的JRE(對在當前開發(fā)環(huán)境中運行的java程序皆生效,也就是在eclipse中運行的java程序)編輯當前使用的JRE,在缺省VM參數(shù)中輸入:

-Xmx1024m -Xms1024m -Xmn256m -Xss16m

 或者在運行一個java程序的時候執(zhí)行:

 java -Xmx1024m

-Xms1024m -Xmn256m -Xss16m Test

 Test是一個class文件。

2. 在Tomcat服務(wù)器上設(shè)置JVM參數(shù)

  set CATALINA_OPTS=-Xmx512m -Xms512m -Xmn64m -Xss2m  或者

  set JAVA_OPTS=-Xmx512m -Xms512m -Xmn64m -Xss2m

  設(shè)置CATALINA_OPTS 和  JAVA_OPTS都是一個道理,在啟動tomcat的時候設(shè)置參數(shù)。

  兩者區(qū)別是JAVA_OPTS在tomcat停止的時候也會執(zhí)行這個命令。

注意:Tomcat分為安裝版(.exe)和非安裝版或者解壓版(.zip),個人還是比較喜歡解壓版。兩者雖然在功能上沒有什么區(qū)別,但是在設(shè)置上還是有要注意的地方。這里只談JVM設(shè)置要注意的地方。

 安裝版:windows的服務(wù)會有一個tomcat服務(wù),當啟動服務(wù)的時候Tomcat會從注冊表讀取JVM的參數(shù)。也就是說當在tomcat的lib文件夾下catalina.bat或者startup.bat中設(shè)置JVM參數(shù)是無效的。解決辦法:設(shè)置tomcat的注冊表;或者使用startup.bat啟動tomcat。

解壓版:當點擊startup.bat時,它會讀取catalina.bat中的配置,不管在startup.bat文件還是在catalina.bat文件中設(shè)置JVM參數(shù),都會讀取JVM參數(shù)。

3. 查看堆的大小

 在程序中查看,返回值單位是字節(jié),當然還有其他JVM參數(shù)可以查看。

 Runtime.getRuntime().maxMemory(); 

或者在命令行 執(zhí)行jvisualvm 命令

 或者%java_home%\bin 目錄下點擊jvisualvm.exe

 或者在命令行執(zhí)行jconsole 命令

 或者%java_home%\bin 目錄下點擊jconsole.exe

4. java內(nèi)存可以分為堆內(nèi)存和非堆內(nèi)存
—- 堆內(nèi)存設(shè)置:程序可以到達的,可以操作的
-Xms 初始堆內(nèi)存 默認物理內(nèi)存1/64,也是最小分配堆內(nèi)存。當空余堆內(nèi)存小于40%時,會增加到-Xms的最大限制

   -Xmx 最大堆內(nèi)存分配 默認物理內(nèi)存1/4,當空余堆內(nèi)存大于70%時,會減小到-Xms的最小限制。
   一般設(shè)置 -Xms和Xms大小相等

   —- 非堆內(nèi)存設(shè)置
  -XX:PermSize 非堆內(nèi)存的初始值,默認物理內(nèi)存的1/64 ,也是最小非堆內(nèi)存。
  -XX:MaxPermSize 非堆內(nèi)存最大值,默認物理內(nèi)存的1/4,

5. 典型JVM參數(shù)設(shè)置:

  java -Xmx128m  -Xms128m -Xmn64m -Xss1m

  -Xmx128m:設(shè)置JVM最大可用內(nèi)存為128M。

  -Xms128m:設(shè)置JVM最小內(nèi)存為128m。此值可以設(shè)置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內(nèi)存。

  -Xmn2g:設(shè)置年輕代大小為2G。整個堆大小=年輕代大小 + 年老代大小 + 持久代大小。持久代一般固定大小為64m,所以增大年輕代后,將會減小年老代大小。此值對系統(tǒng)性能影響較大,Sun官方推薦配置為整個堆的3/8。

  -Xss128k:設(shè)置每個線程的堆棧大小。 JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。根據(jù)應(yīng)用的線程所需內(nèi)存大小進行調(diào)整。在相同物理內(nèi)存下,減小這個值能生成更 多的線程。但是操作系統(tǒng)對一個進程內(nèi)的線程數(shù)還是有限制的,不能無限生成,經(jīng)驗值在3000~5000左右。

  — Ratio 英音:[‘reiseu] 比率
  — Eden 伊甸
  — Survivor 幸存者

  java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0

  -XX:NewRatio=4:設(shè)置年輕代(包括Eden和兩個Survivor區(qū))與年老代的比值(除去持久代)。設(shè)置為4,則年輕代與年老代所占比值為1:4,年輕代占整個堆棧的1/5

  -XX:SurvivorRatio=4:設(shè)置年輕代中Eden區(qū)與Survivor區(qū)的大小比值。設(shè)置為4,則兩個Survivor區(qū)與一個Eden區(qū)的比值為2:4,一個Survivor區(qū)占整個年輕代的1/6

  -XX:MaxPermSize=16m:設(shè)置持久代大小為16m。

  -XX:MaxTenuringThreshold=0:設(shè)置垃圾最大年齡。如果設(shè)置為0的話,則年輕代對象不經(jīng)過Survivor區(qū),直接進入年老代。
對于年老代比較多的應(yīng)用,可以提高效率。如果將此值設(shè)置為一個較大值,則年輕代對象會在Survivor區(qū)進行多次復(fù)制,這樣可以增加對象再年輕代的存活時間,增加在年輕代即被回收的概論。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容