亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

JAVA應用生產問題排查步驟

學會這篇文章里面的命令并熟練使用,出去面試就可以說自己有5年工作經驗并且精通JVM了。本篇文章中介紹的命令絕對是JAVA程序員平時工作中經常使用的并且必須會的命令,如果你不會你就是沒有工作經驗的人。如果你不會,那么在別人眼中你肯定就是菜鳥一個,所以本篇文章中的命令,你必須學會并且熟練使用。

注意:本篇文章內容基于JDK版本:

java version “1.6.0_113”

Java™ SE Runtime Environment (build 1.6.0_113-b01)

Java HotSpot™ 64-Bit Server VM (build 20.111-b01, mixed mode)

1 JAVA自帶命令JPS

jps這個命令在JDK的安裝目錄bin/下面

JAVA應用生產問題排查步驟

 

使用jps這個命令可以找到運行在服務器(電腦)上面的所有JVM進程。jps最常用、最有用的命令有以下倆個。

  • jps -vljps -vl這個命令中的-v是輸出啟動JVM進程時傳遞給JVM的參數,-l是輸出main方法所在類的完整路徑或者JAR包的完成路徑,命令結果如下截圖:
  • jps -mljps -ml這個命令中的-m是輸出傳給main方法的參數,-l是輸出main方法所在類的完整路徑或者JAR包的完成路徑,命令結果如下截圖:在Liunx服務器上面執行jps -ml結果如下截圖:工作中最常用的命令是jps -vl。jps -ml這個命令結果比較雞肋并且不常用。你可以自己寫一個main方法,在main方法里面寫一個死循環,并且傳遞給main方法幾個參數,然后再執行一下jps -vl和jps -ml這倆個命令感受一下。你如果光看我的文章,自己不手敲這些命令,你就是瞎看,沒一點用。

如果你們公司是通過weblogic部署的應用,那么weblogic啟動的時候會給JVM進程傳一個參數-Dweblogic.Name= yourwebname ,這個 yourwebname 就是你部署應用的應用名稱,然后你可以通過jps -vl |grep yourwebname 這個命令找到你javaweb項目的jvm進程id。

但是,如果你的應用是通過Tomcat部署,那么jps -vl |grep yourwenname 這個命令就不太管用了。不過jps -vl 這個命令肯定還是管用的,因為jps是java自帶的命令,跟tomcat或者weblogic沒有任何關系。

如果你的應用部署在tomcat上面,那么你就用jps -vl 找tomcat這個JVM進程就可以了。原理如下:

一個tomcat就只能啟動一個JVM進程,如果你的tomcat里面部署了多個Java Web應用, 那么你的多個Java Web應用共享這個一個JVM,每個JavaWeb應用都有自己的ClassLoader,也就是說一個JVM中可以有多個Class Loader。

如果其中一個JavaWeb應用發生了內存泄漏或者別的原因把JVM搞垮了,那么這個tomcat下面的所有JavaWeb應用就全掛了,所以生產環境沒有人會用一個tomcat去部署多個JavaWeb應用的。生產環境,都是啟動多個tomcat,每個tomcat只部署一個JavaWeb應用。

我感覺一個tomcat只能啟動一個JVM進程這個設計非常不合理,假如我一個tomcat下面部署了多個JavaWeb應用,我想給每個JavaWeb應用設置不同的JVM參數都不行。現在的SpringBoot應用都是直接通過java -jar App.jar啟動的,并且SpringBoot直接就內置了一個tomcat,所以你通過java -jar app.jar啟動的時候就是一個tomcat只部署一個We應用。

關于tomcat的知識我是參考CSDN網站上面的大神greencacti的文章: Tomcat中會啟動一個jvm還是多個jvm? 。

還有CSDN網站上面的大神tyyh08的文章

一個tomcat部署多個應用,有幾個JVM? 。

2 Liunx上面top命令

使用jps命令找到我們的jvm進程ID之后趕緊使用top命令看一下服務器上面的大致情況,top命令默認好像是3秒鐘刷新一次。

top 命令結果如下截圖:

JAVA應用生產問題排查步驟

 

top命令結果顯示之后按小寫字母c,可以顯示完整的命令行,這個非常有用,一定要用。如截圖

JAVA應用生產問題排查步驟

 

然后按大寫母P,以CPU使用率排序(按進程負載排序,排在最上面的就是CPU使用率最高的)

JAVA應用生產問題排查步驟

 

按大寫字母M,以內存使用率排序

JAVA應用生產問題排查步驟

 

高亮顯示:可以這樣搞,先按大寫字母P,再按小寫字母b,再按小寫字母x。效果如下截圖:

JAVA應用生產問題排查步驟

 

按鍵b打開或關閉 運行中進程的高亮效果

按鍵x打開或關閉 排序列的高亮效果

按數字 1 鍵,可以顯示多個CPU的使用情況

JAVA應用生產問題排查步驟

 

top顯示的是服務器上面所有的進程概況,top類似于windows電腦上面的的任務管理器。

JAVA應用生產問題排查步驟

 

但是,如果我只關心我自己的JVM進程呢?可以使用這個命令

top -p jvm進程ID,這個命令可以指定進程,只顯示指定進程的概況,按空格鍵可以立即刷新。

JAVA應用生產問題排查步驟

 

top -d 2 -p jvm進程ID,這個命令可以指定進程,只顯示指定進程的概況,-d 2的意思是倆秒鐘刷新一次。

JAVA應用生產問題排查步驟

 

top -Hp 進程ID,這個命令可以顯示指定進程下面的線程信息, 這個超級有用,必須要會。 而且這個命令搭配JAVA的自帶命令jstack可以非常快速并且有效的定位代碼問題。

JAVA應用生產問題排查步驟

 

然后使用linux的自帶命令,printf將線程ID轉換成16進制,printf “0x%xn” 19235

JAVA應用生產問題排查步驟

 

然后使用JAVA的自帶命令jstack去找到這個線程ID都在干什么就行了。這幾個命令非常非常重要。

使用top命令,其實主要關注top命令里面的RES列的值,%CPU列的值,%MEM列的值,這三列的值就行了。然后

拿RES列的值跟后面jmap命令顯示的jvm堆的值做比較。如果RES的值,比你的Xmx的值還大, 注意是比你設置的Xmx的值還大 ,說明你的java程序引用的有非堆(堆外地址)內存,比如NIO,DirectByteBuffer這些類會使用堆外的內存。所以要注意堆外內存泄露情況(就是你代碼里面雖然已經不用這塊堆外地址了,但是你的引用沒釋放,導致你的程序浪費了很多用不到的堆外地址)。 堆外內存泄漏可以使用google出品的perf工具來排查。perf工具使用參見,大神的文章 feininan 的文章《 使用google perf工具來排查堆外內存占用 》。

這塊知識點摘自網絡上面 MartinDai 大神的文章 記一次堆外內存泄漏排查過程 。 執行top命令,再按c,看到對應的進程所占用的RES有8個多G(這里當時忘記截圖了),但是實際上我們配置的Xmx只有3G,而且程序還是正常運行的,所以不會是堆占用了這么多,于是就把問題方向指向了非堆的內存。

RES列和%MEM列的關系為:RES/總內存=%MEM,我們來算一下:

JAVA應用生產問題排查步驟

 

從上圖可以看到,這臺服務器的物理內存(運存)為:132024628k = 126G.

32924這個進程的RES列的值為:5.3G

32924這個進程的%MEM列的值為:4.2%

我們來算一下:RES:5.3G / total Mem:126G = 0.042 = 4.2%

這下你明白了吧RES列和%MEM列,表達的其實是一個意思。

RES的意思是:Resident Memory Size 常駐內存大小。使用man top命令看下top命令的官方幫助文檔怎么說:

JAVA應用生產問題排查步驟

 


JAVA應用生產問題排查步驟

 


JAVA應用生產問題排查步驟

 

TIPS:按小寫字母q可以退出top命令

JVM進程的RES列的值和JVM的heap(堆)的關系也很有意思,RES列的值代表JVM進程在運行過程中曾經使用過的最大內存, 注意是曾經使用過的最大內存 ,并不代表此時此刻JVM堆使用的內存大小。舉個例子,假如JVM在業務高峰期有大量請求進來,此時堆內存使用量肯定會上升,假如此時堆內存的使用量為5G,然后觸發了JVM的垃圾回收,垃圾回收之后JVM堆內存使用量下降到了1G,此時你用top命令去看這個JVM進程的RES列的值有很大可能還是5G,原因就是這5G內存目前還歸屬JVM進程管理并使用,JVM 可能不會立即 把回收掉的堆空間還給操作系統。

只要RES列的值不大于我們給JVM設置Xmx的值,就沒有關系。Xmx這個參數的意思就是告訴操作系統,JVM本大爺我有可能要使用Xmx這么大的內存,你操作系統提前做好心理準備。JVM進程剛運行的時候并不會直接找操作系統要Xmx這么大的內存,JVM在運行的過程中根據自己的情況一點一點問操作系統申請的。一旦JVM進程從操作系統申請到內存之后,JVM在運行的過程中就可能就不會還給操作系統了。因為JVM跟操作系統之間如果總是借呀還呀的就會很浪費性能,沒有什么必要。JVM進程退出之后占用的這些內存肯定會釋放給操作系統的。關于JVM是否把空閑的堆(heap)內存還給操作系統這件事,JVM提供了一些參數:

-XX:MinHeapFreeRatio、

-XX:MaxHeapFreeRatio、

-XX:-ShrinkHeapInSteps

這幾個參數你們自己查資料吧。

怎么驗證這個說法?先找一個運行了1天以上的JVM進程,然后使用top命令看下這個JVM進程的RES列的值,然后再用我后面介紹的jmap -heap 19463 命令看一下JVM進程堆的使用情況就知道了。

這塊知識點摘自掘金APP上面 空無 大神的文章《 運維:你們 JAVA 服務內存占用太高,還只增不減!告警了,快來接鍋 》。

熊峰 大神的文章《 JVM調優之探索CMS和G1的物理內存歸還機制 》。

stackoverflow 網站的提問《 Does GC release back memory to OS? 》。

Oracle官方文檔《 Default Option Values for Heap Size 》。

3 JAVA自帶命令–jstat,查看GC(垃圾回收情況)

jstat這個命令在JDK的安裝目錄bin/下面

JAVA應用生產問題排查步驟

 

3.1 使用 jstat 查看 GC(垃圾回收) 的情況

jstat -gc jvm進程PID 2000

這個命令會每隔2秒統計一下JVM進程(PID):19463的垃圾收集情況,命令最后2000的意思就是每隔2秒統計一次。使用jstat命令可以實時監測到YGC和FGC的情況,包括每次YGC和FGC各花費了多長時間,到目前為止總共進行了多少次YGC和FGC。

JAVA應用生產問題排查步驟

 

jstat -gcutil jvm進程PID 2000

這個命令里面的-gcutil 監視內容與-gc基本相同,但輸出主要關注已使用空間占總空間的百分比 。

JAVA應用生產問題排查步驟

 

也可以寫成 jstat -gcutil jvm進程PID 2s , 2s也是2秒鐘刷新一次的意思。還有一種寫法是 jstat -gcutil 19463 2s 5 ,這個命令是2秒鐘刷新一次,總共統計5次就行了,5次之后自動結束jstat命令,不需要你手工按crtl+c去終止命令。

JAVA應用生產問題排查步驟

 

–gcutil監視內容 與 -gc基本相同,但輸出主要關注已使用空間占總空間的 百分比 。

jstat -gccause 28549 2000

gccause 與-gcutil功能一樣,但是會額外輸出導致上一次GC產生的原因

JAVA應用生產問題排查步驟

 

工作中我個人使用jstat -gccause和jstat -gc這個倆個命令比較多。

3.2 jstat輸出內容解釋

  • jstat -gc jvm進程PID 2000
JAVA應用生產問題排查步驟

 

jvm的堆(heap)空間由S0(Survivor,0號幸存區)+S1(Survivor,1號幸存區)+Eden(年輕代)+Tenured(Old老年代)+Permanent(永久代)組成的。

注意:Permanent(永久代)在jdk1.7還是jdk1.8的時候被移除了,換成Metaspace(元數據)了。注意,永久代的意思并不是這塊內存永遠不會回收,在發生FullGC的時候,永久代里面的垃圾也會被回收掉。

所以jstat的輸出結果說明為:

S0C(Capacity):S0的最大內存,總內存。Capacity就是容量的意思。單位:kb

S0U(Used):S0目前已經使用的大小。Used就是已經使用的意思。單位:kb

EC,EU:就是年輕代

PC,PU:就是永久代

OC,OU:就是老年代

YGC:就是年輕代的GC次數

YGCT:就是年輕代GC所花費的時間,單位秒

FGC:就是FGC的次數

FGCT:就是FGC所花費的時間,單位秒

GCT:就是YGC+FGC倆個GC加起來所花費的時間,單位秒

  • jstat -gcutil 4777 2000 5
JAVA應用生產問題排查步驟

 

這個命令里面的-gcutil 監視內容與-gc基本相同,但輸出主要關注已使用空間占總空間的百分比,所以-gcutil看到的是使用率。

這些命令你會使用了,關鍵結果你能看得懂嗎?其實很簡單,我們主要關注,年輕代和老年代和持久代的使用率,目前用了多少G,最大的堆內存空間配置的是多少?是不是快滿了,是不是快要內存溢出了就行。GC前后的年輕代和老年代占用的空間是否減少了,如果發生了一次GC,年輕代和老年代占用的空間并沒有減少,那說明你的代碼發生了內存泄漏。要趕緊使用我下面介紹的jmap命令將java的堆現場的情況dump下來使用MAT軟件或者GCeasy或者visualVM或者國內PerfMa社區的軟件來分析dump內存文件,找到代碼泄漏的真正原因。Perfma社區的 阿飛Javaer 大神說FullGC一天超過一次肯定就不正常了,發現FullGC頻繁的時候優先調查內存泄漏問題。我認為這個說法不太對,我看了一下,我們生產環境的GC情況,FullGC一天500次左右,服務也挺正常的。并且老年代回收完使用率才13%,說明我們生產環境FullGC是可以把垃圾回收掉的。FullGC的次數本質是跟JVM的內存使用量有關系的,如果你們的系統業務很繁忙,FullGC次數多也是正常的,只有GC之后能把垃圾都回收掉就可以。并且每次FullGC的STW線程停頓時間不長也沒有關系的。

4. JAVA自帶命令–jinfo,查看JVM的配置信息

jinfo這個命令在JDK的安裝目錄bin/下面

JAVA應用生產問題排查步驟

 

jinfo -flags 12832

這個命令可以查看我們給JVM設置的配置項和參數(默認+人工配置)

JAVA應用生產問題排查步驟

 

這個命令沒啥說的,很簡單就是看我們給JVM設置的一些參數信息。

jinfo -flag MaxPermSize 1919,注意這個命令flag后面沒有帶s,這個命令用來看我們有沒有給JVM設置MaxPermSize這個參數。如果有,就將設置的值顯示出來。

JAVA應用生產問題排查步驟

 

可以看到我,我給JVM設置的永久代MaxPermSize的最大空間為:-XX:MaxPermSize=1073741824(1個G)

jinfo -flag HeapDumpPath 111552

jinfo -flag MetaspaceSize 111552

jinfo -flag 這個命令不常用,最常用的就是 jinfo -flags 這個帶s的直接看所有的JVM配置。

使用jinfo命令可以看到我們指定的-Xmx 堆的最大值。這里還有一個經驗就是,最好將Xms(jvm堆heap的初始化大小) -Xmx(jvm堆heap的最大值),這個倆個的值設置為一樣的,避免每次垃圾回收完成后JVM重新分配內存,可以防止在每次GC后進行內存重新分配,這塊知識來自 Perfma社區的 阿飛Javaer

5. JAVA自帶命令–jmap,查看heap(堆)的內存使用情況

jmap這個命令在JDK的安裝目錄bin/下面

JAVA應用生產問題排查步驟

 

jmap -heap 19463 查看java 堆(heap)使用情況

注意看我的截圖,一定要放大了截圖,然后仔細看

JAVA應用生產問題排查步驟

 

jmap -histo 19463 查看堆內存(histogram)中的對象數量及大小

JAVA應用生產問題排查步驟

 

jmap -histo 19463 | head -n100 只顯示前100行

JAVA應用生產問題排查步驟

 

或者使用 jmap -histo:live 19463 | more 查看,使用more命令查看

JAVA應用生產問題排查步驟

 

TIPS:more命令按空格可以翻頁查看,按小寫字母q可以退出more命令。

jmap -histo:live 19463 這個命令會先觸發JVM執行GC(垃圾回收),然后再統計信息。為什么要先觸發GC呢?因為這個命令live只統計活著的對象。

jmap -dump:format=b,file=9739_jvm_heap.hprof 9739

先解釋一下什么叫做dump。dump的意思是轉存儲,那什么叫做轉存儲呢?轉存儲就是將內存(運存)中的數據導出,然后保存(持久化)下來。我們都知道APP(程序)在運行的時候也會產生一些臨時數據或者APP(程序)在運行的時候也需要臨時存儲一些數據。這些數據的存儲都是臨時性的,一旦APP(程序)運行結束,這些數據就都消失了。所以當JVM運行的過程中出現問題的時候,注意是JVM在運行的時候出問題了,我們就需要把JVM運行時內存(heap堆)的情況dump(轉存儲),然后分析一下JVM的heap(堆)上面目前是什么情況?

JAVA應用生產問題排查步驟

 

注意:執行該命令的時候會將整個JVM上面的所有線程都暫停,如果你的java堆比較大,比如有10個G左右,那暫停的時間可能比較長,有可能長達10分鐘,所以在生產環境慎用這個命令。或者在生產環境,先讓運維把請求都先負載到別的機器上面,再執行這個命令。

執行完成后在當前目錄就會產生一個9739_jvm_heap.hprof 的文件

JAVA應用生產問題排查步驟

 

jmap -dump: live ,format=b,file=heapLive.hprof 9739 如果帶上live會先觸發一次GC,GC完則只轉存儲活著的對象。

然后,這個文件是二進制的文件,人肯定是看不懂的。所以,需要借助分析dump文件的工具,可以使用工具來分析:

  • 國內PerfMa社區的XElephant在線工具網站為 https://console.perfma.com/ , https://memory.console.perfma.com/
JAVA應用生產問題排查步驟

 


JAVA應用生產問題排查步驟

 

  • GCeasy

網站為 https://gceasy.io/

JAVA應用生產問題排查步驟

 

  • Memory Analyzer (MAT)

網站為
https://www.eclipse.org/mat/

JAVA應用生產問題排查步驟

 

MAT這個工具有一個MemoryAnalyzer.ini配置文件:找到MemoryAnalyzer.ini文件,該文件里面有個Xmx參數,該參數表示最大內存占用量,默認為1024m,根據堆轉儲文件大小修改該參數即可。MAT工具要求dump文件的后綴名以.hprof結尾。B站 PerfMa up主 JVM字節碼的探索與實踐應用(第一期)直播回放 在第56秒說:如果dump文件太大,MAT也會打不開。

JAVA應用生產問題排查步驟

 

至于這些分析JAVA dump文件的工具怎么用,你們可以自己去Google一下,我后面也會再寫一篇關于這些工具的教程。不過有一點需要注意,如果你dump出來的文件很大,那么上面的工具就都不管用了,比如說你dump出來的文件大小為10G,這么大的文件上面的工具想打開一個10G的文件也非常困難了。要知道分析dump文件的工具本身也是一個APP,這個APP要分析這個10G的dump文件也需要把這個10個G的文件加載到自己的內存中去,10G他肯定是不好加載的。這個時候你只能使用 jmap -histo 32924 | head -n 60 這個命令手動來查看堆內存上面什么對象最多了,這個命令的截圖如下:

JAVA應用生產問題排查步驟

 

如果你發現這個命令的結果里面有你熟悉的類,那很大可能就是你項目中這個類的對象生成的太多了,并且使用完之后沒有釋放造成了內存泄漏,是有可能并不是絕對的,這個只能當線索去分析,不能當證據去使用。

如果你要看jmap -histo 32924這個命令的全部結果,可以使用jmap -histo 32924 > /tmp/java_heap_32924.txt這個命令,將命令的結果保存到文件中,然后將文件下載到本地查看。

這塊知識來自 網絡上的大神:Hollis Java命令學習系列(三)——Jmap

博客園上面的大神:星朝 JVM性能調優實踐——JVM篇

HeapDump社區上面的大神Coder的技術之路 高并發服務優化篇:詳解一次由讀寫鎖引起的內存泄漏

HeapDump社區上面的大神:Java小能手 記一次線上服務CPU 100%的處理過程

6. JAVA自帶命令–jstack,查看JVM內所有的線程運行情況

jstack這個命令在JDK的安裝目錄bin/下面

JAVA應用生產問題排查步驟

 

這個命令也比較簡單,沒啥好講的, 但是非常重要,分析問題時超級有用。 命令就是jstack -l JVMPID就行了。這個命令配合我們前面講的 top -Hp 19235 命令和 printf將線程ID轉換成16進制 printf “0x%xn” 19235 ,能非常快速定位JAVA程序中運行卡頓和緩慢的性能問題。

jstack -l 9739

JAVA應用生產問題排查步驟

 

jstack -l 9739 > /tmp/9739_jvm_thread.dump

將jstack -l 9739的命令的全部輸出結果都保存到文件里面去,然后再下載的本地或者網上去分析。

JAVA應用生產問題排查步驟

 

打開JAVA線程dump文件

JAVA應用生產問題排查步驟

 

打開JAVA線程dump文件之后,我們就可以利用上面我們講過的 top -Hp 19235 命令和 printf將線程ID轉換成16進制 printf “0x%xn” 19235 ,拿到最占CPU的線程ID之后,來這個JAVA線程dump文件里面搜索這個線程,就知道這個線程在干嘛了,卡在了哪一行。

grep ‘java.lang.Thread.State’ /tmp/9739_jvm_thread.dump | wc -l

統計總共有多少線程,線程總數。線程如果太多肯定是有問題的,至于多少線程算多我也不知道。觀察唄,就跟袁隆平老爺子一樣,你沒事多下地觀察一下水稻是怎么生長的就知道了,經驗就是這么來的。你們項目平時正常運行的時候,你上去統計一下,等過一段時間你們項目真出問題了你跟平時的經驗對比一下就小蔥拌豆腐一清二白了。

JAVA應用生產問題排查步驟

 

grep “java.lang.Thread.State” /tmp/20210713_thread.log |sort| uniq -c | sort -nr

grep “java.lang.Thread.State”
/tmp/20210713_vhlthread.log |sort| uniq -c | sort -nr 使用這個命令看下所有的線程都處于什么狀態

JAVA應用生產問題排查步驟

 

上面介紹的命令使用起來畢竟太原始,效率太低了,不是人干的事。區分一個程序猿到底猴子還是人,主要看他會不會使用工具。介紹倆個分析線程快照的工具:

  • fastThread

網站為 https://fastthread的具體使用教程,你們自己網上Google吧。.io/

JAVA應用生產問題排查步驟

 

分析結果

JAVA應用生產問題排查步驟

 


JAVA應用生產問題排查步驟

 


JAVA應用生產問題排查步驟

 

fastthread的具體使用教程,你們自己網上Google吧。

  • 國內HeapDump社區的XSheepdog在線工具網站為 https://www.perfma.com/ , https://console.heapdump.cn/
JAVA應用生產問題排查步驟

 


JAVA應用生產問題排查步驟

 


JAVA應用生產問題排查步驟

 

更多用法需要你自己動手去挖掘。

如果您覺得文章對您有用,請轉發、評論謝謝~

原文鏈接:
https://www.tuicool.com/articles/Ej6neiE

分享到:
標簽:JAVA
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定