java虛擬機內存監控_深入理解JVM虛擬機9:JVM監控工具與診斷實踐

本文轉自:

https://juejin.im/post/59e6c1f26fb9a0451c397a8c

本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到我的倉庫里查看

https://github.com/h3pl/Java-Tutorial

喜歡的話麻煩點下Star哈

文章將同步到我的個人博客:

www.how2playlife.com

本文是微信公眾號【Java技術江湖】的《深入理解JVM虛擬機》其中一篇,本文部分內容來源于網絡,為了把本文主題講得清晰透徹,也整合了很多我認為不錯的技術博客內容,引用其中了一些比較好的博客文章,如有侵權,請聯系作者。

該系列博文會告訴你如何從入門到進階,一步步地學習JVM基礎知識,并上手進行JVM調優實戰,JVM是每一個Java工程師必須要學習和理解的知識點,你必須要掌握其實現原理,才能更完整地了解整個Java技術體系,形成自己的知識框架。

為了更好地總結和檢驗你的學習成果,本系列文章也會提供每個知識點對應的面試題以及參考答案。

如果對本系列文章有什么建議,或者是有什么疑問的話,也可以關注公眾號【Java技術江湖】聯系作者,歡迎你參與本系列博文的創作和修訂。

在常見的線上問題時候,我們多數會遇到以下問題:

內存泄露

某個進程突然cpu飆升

線程死鎖

響應變慢…等等其他問題。

如果遇到了以上這種問題,在線下可以有各種本地工具支持查看,但到線上了,就沒有這么多的本地調試工具支持,我們該如何基于監控工具來進行定位問題?

我們一般會基于數據收集來定位,而數據的收集離不開監控工具的處理,比如:運行日志、異常堆棧、GC日志、線程快照、堆快照等。經常使用恰當的分析和監控工具可以加快我們的分析數據、定位解決問題的速度。以下我們將會詳細介紹。

一、jvm常見監控工具&指令

1、 jps:jvm進程狀況工具

jps [options] [hostid]復制代碼

如果不指定hostid就默認為當前主機或服務器。

命令行參數選項說明如下:

-q 不輸出類名、Jar名和傳入main方法的參數

- l 輸出main類或Jar的全限名

-m 輸出傳入main方法的參數

- v 輸出傳入JVM的參數復制代碼

2、jstat: jvm統計信息監控工具

jstat 是用于見識虛擬機各種運行狀態信息的命令行工具。它可以顯示本地或者遠程虛擬機進程中的類裝載、內存、垃圾收集、jit編譯等運行數據,它是線上定位jvm性能的首選工具。

命令格式:

jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]

generalOption - 單個的常用的命令行選項,如-help, -options, 或 -version。

outputOptions -一個或多個輸出選項,由單個的statOption選項組成,可以和-t, -h, and -J等選項配合使用。復制代碼

參數選項:

Option

Displays

Ex

class

用于查看類加載情況的統計

jstat -class pid:顯示加載class的數量,及所占空間等信息。

compiler

查看HotSpot中即時編譯器編譯情況的統計

jstat -compiler pid:顯示VM實時編譯的數量等信息。

gc

查看JVM中堆的垃圾收集情況的統計

jstat -gc pid:可以顯示gc的信息,查看gc的次數,及時間。其中最后五項,分別是young gc的次數,young gc的時間,full gc的次數,full gc的時間,gc的總時間。

gccapacity

查看新生代、老生代及持久代的存儲容量情況

jstat -gccapacity:可以顯示,VM內存中三代(young,old,perm)對象的使用和占用大小

gccause

查看垃圾收集的統計情況(這個和-gcutil選項一樣),如果有發生垃圾收集,它還會顯示最后一次及當前正在發生垃圾收集的原因。

jstat -gccause:顯示gc原因

gcnew

查看新生代垃圾收集的情況

jstat -gcnew pid:new對象的信息

gcnewcapacity

用于查看新生代的存儲容量情況

jstat -gcnewcapacity pid:new對象的信息及其占用量

gcold

用于查看老生代及持久代發生GC的情況

jstat -gcold pid:old對象的信息

gcoldcapacity

用于查看老生代的容量

jstat -gcoldcapacity pid:old對象的信息及其占用量

gcpermcapacity

用于查看持久代的容量

jstat -gcpermcapacity pid: perm對象的信息及其占用量

gcutil

查看新生代、老生代及持代垃圾收集的情況

jstat -util pid:統計gc信息統計

printcompilation

HotSpot編譯方法的統計

jstat -printcompilation pid:當前VM執行的信息

例如:

查看gc 情況執行:jstat-gcutil 27777

3、jinfo: java配置信息

命令格式:

jinfo[option] pid復制代碼

比如:獲取一些當前進程的jvm運行和啟動信息。

4、jmap: java 內存映射工具

jmap命令用于生產堆轉存快照。打印出某個java進程(使用pid)內存內的,所有‘對象’的情況(如:產生那些對象,及其數量)。

命令格式:

jmap [ option ] pid

jmap [ option ] executable core

jmap [ option ] [server-id@]remote-hostname-or-IP復制代碼

參數選項:

-dump:[live,]format=b,file= 使用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、jhat:jvm堆快照分析工具

jhat 命令與jamp搭配使用,用來分析map生產的堆快存儲快照。jhat內置了一個微型http/Html服務器,可以在瀏覽器找那個查看。不過建議盡量不用,既然有dumpt文件,可以從生產環境拉取下來,然后通過本地可視化工具來分析,這樣既減輕了線上服務器壓力,有可以分析的足夠詳盡(比如 MAT/jprofile/visualVm)等。

6、jstack:java堆棧跟蹤工具

jstack用于生成java虛擬機當前時刻的線程快照。線程快照是當前java虛擬機內每一條線程正在執行的方法堆棧的集合,生成線程快照的主要目的是定位線程出現長時間停頓的原因,如線程間死鎖、死循環、請求外部資源導致的長時間等待等。

命令格式:

jstack [ option ] pid

jstack [ option ] executable core

jstack [ option ] [server-id@]remote-hostname-or-IP復制代碼

參數:

-F當’jstack [-l] pid’沒有相應的時候強制打印棧信息

-l長列表. 打印關于鎖的附加信息,例如屬于java.util.concurrent的ownable synchronizers列表.

-m打印java和native c/c++框架的所有棧信息.

-h | -help打印幫助信息

pid 需要被打印配置信息的java進程id,可以用jps查詢.復制代碼

后續的查找耗費最高cpu例子會用到。

二、可視化工具

對jvm監控的常見可視化工具,除了jdk本身提供的Jconsole和visualVm以外,還有第三方提供的jprofilter,perfino,Yourkit,Perf4j,JProbe,MAT等。這些工具都極大的豐富了我們定位以及優化jvm方式。

這些工具的使用,網上有很多教程提供,這里就不再過多介紹了。對于VisualVm來說,比較推薦使用,它除了對jvm的侵入性比較低以外,還是jdk團隊自己開發的,相信以后功能會更加豐富和完善。jprofilter對于第三方監控工具,提供的功能和可視化最為完善,目前多數ide都支持其插件,對于上線前的調試以及性能調優可以配合使用。

另外對于線上dump的heap信息,應該盡量拉去到線下用于可視化工具來分析,這樣分析更詳細。如果對于一些緊急的問題,必須需要通過線上監控,可以采用 VisualVm的遠程功能來進行,這需要使用tool.jar下的MAT功能。

三、應用

1、cpu飆升

在線上有時候某個時刻,可能會出現應用某個時刻突然cpu飆升的問題。對此我們應該熟悉一些指令,快速排查對應代碼。

1.找到最耗CPU的進程

指令:top復制代碼

2.找到該進程下最耗費cpu的線程

指令:top -Hp pid復制代碼

3.轉換進制

printf “%x\n” 15332 // 轉換16進制(轉換后為0x3be4) 復制代碼

4.過濾指定線程,打印堆棧信息

指令:

jstack pid |grep 'threadPid' -C5 --color

jstack 13525 |grep '0x3be4' -C5 --color // 打印進程堆棧 并通過線程id,過濾得到線程堆棧信息。復制代碼

可以看到是一個上報程序,占用過多cpu了(以上例子只為示例,本身耗費cpu并不高)

2、線程死鎖

有時候部署場景會有線程死鎖的問題發生,但又不常見。此時我們采用jstack查看下一下。比如說我們現在已經有一個線程死鎖的程序,導致某些操作waiting中。

1.查找java進程id

指令:top 或者 jps 復制代碼

2.查看java進程的線程快照信息

指令:jstack -l pid復制代碼

從輸出信息可以看到,有一個線程死鎖發生,并且指出了那行代碼出現的。如此可以快速排查問題。

3、OOM內存泄露

java堆內的OOM異常是實際應用中常見的內存溢出異常。一般我們都是先通過內存映射分析工具(比如MAT)對dump出來的堆轉存快照進行分析,確認內存中對象是否出現問題。

當然了出現OOM的原因有很多,并非是堆中申請資源不足一種情況。還有可能是申請太多資源沒有釋放,或者是頻繁頻繁申請,系統資源耗盡。針對這三種情況我需要一一排查。

OOM的三種情況:

1.申請資源(內存)過小,不夠用。

2.申請資源太多,沒有釋放。

3.申請資源過多,資源耗盡。比如:線程過多,線程內存過大等。

1.排查申請申請資源問題。

指令:jmap -heap 11869 復制代碼

查看新生代,老生代堆內存的分配大小以及使用情況,看是否本身分配過小。

從上述排查,發現程序申請的內存沒有問題。

2.排查gc

特別是fgc情況下,各個分代內存情況。

指令:jstat -gcutil 11938 1000 每秒輸出一次gc的分代內存分配情況,以及gc時間復制代碼

3.查找最費內存的對象

指令: jmap -histo:live 11869 | more復制代碼

上述輸出信息中,最大內存對象才161kb,屬于正常范圍。如果某個對象占用空間很大,比如超過了100Mb,應該著重分析,為何沒有釋放。

注意,上述指令:

jmap -histo:live 11869 | more

執行之后,會造成jvm強制執行一次fgc,在線上不推薦使用,可以采取dump內存快照,線下采用可視化工具進行分析,更加詳盡。

jmap -dump:format=b,file=/tmp/dump.dat 11869

或者采用線上運維工具,自動化處理,方便快速定位,遺失出錯時間。復制代碼

4.確認資源是否耗盡

pstree 查看進程線程數量

netstat 查看網絡連接數量

或者采用:

ll /proc/${PID}/fd | wc -l // 打開的句柄數

ll /proc/${PID}/task | wc -l (效果等同pstree -p | wc -l) //打開的線程數

以上就是一些常見的jvm命令應用。

一種工具的應用并非是萬能,包治百病,問題的解決往往是需要多種工具的結合才能更好的定位問題,無論使用何種分析工具,最重要的是熟悉每種工具的優勢和劣勢。這樣才能取長補短,配合使用。

參考文章

https://segmentfault.com/a/1190000009707894

https://www.cnblogs.com/hysum/p/7100874.html

http://c.biancheng.net/view/939.html

https://www.runoob.com/

https://blog.csdn.net/android_hl/article/details/53228348

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/378762.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/378762.shtml
英文地址,請注明出處:http://en.pswp.cn/news/378762.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

詳解:數據庫名、實例名、ORACLE_SID、數據庫域名、全局數據庫名、服務名

數據庫名、實例名、數據庫域名、全局數據庫名、服務名,這是幾個令很多初學者容易混淆的概念。相信很多初學者都與我一樣被標題上這些個概念搞得一頭霧水。我們現在就來把它們弄個明白。 一、數據庫名什么是數據庫名?數據庫名就是一個數據庫的標識&#…

顏色縮減 -利用指針、迭代器、動態地址實現訪問像素

為什么要使用顏色縮減 在對單通道圖像進行處理時,像素的可能值為256個,但處理多通道時,像素的處理就會相當麻煩,其實用這些顏色中具有代表性的一小部分就可以達到同樣的效果,所以顏色空間縮減就可以派上用場了。一個信…

setlenient_Java日歷setLenient()方法與示例

setlenient日歷類setLenient()方法 (Calendar Class setLenient() method) setLenient() method is available in java.util package. setLenient()方法在java.util包中可用。 setLenient() method is used to set or unset lenient status of date or time interpretations. s…

PowerShell_9_零基礎自學課程_9_高級主題:靜態類和類的操作

哈哈,昨天弄了個ubuntu 11.10在虛擬機上運行,發現11.10界面非常絢麗,但是其需要的系統資源非常多,我虛擬機設定內存為512M,1個CPU4個核心, 進入以后發現根本動不了,因此今天我就下載了一個Fedor…

05-圖像的平滑處理(不同的濾波操作)

對圖像進行平滑處理實則就是對圖像進行濾波操作罷了 每張圖片都有若干個像素點所構成,濾波操作上就是將照片上的某些部分像素點進行修改從而達到平滑的效果 先展示一下原圖 import cv2 img cv2.imread(E:\Jupyter_workspace\study\data/test1.png)cv2.imshow(te…

js刪除mysql記錄_(DELETEUPDATE)修改、刪除數據記錄_MySQL

有時,希望除去某些記錄或更改它們的內容。DELETE 和 UPDATE 語句令我們能做到這一點。用update修改記錄UPDATE tbl_name SET 要更改的列WHERE 要更新的記錄這里的 WHERE 子句是可選的,因此如果不指定的話,表中的每個記錄都被更新。例如&#…

C++設計模式之Abstract Factory模式

一、功能   提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。 二、結構圖類廠最基本的結構示意圖如下: 在實際應用中,類廠模式可以擴充到很復雜的情況,如下圖所示: 三、優缺點 優點&#xff1…

數字圖像處理小練習存檔1

小練習的題目: 1、讀取一張圖,分解RGB三個通道 /************練習1**********************/ int main() {Mat img1 imread("D:\\opencv_picture_test\\miku2.jpg",2|4); //灰度圖if (img1.empty()){printf("Could not find the imag…

UIImage 壓縮

1.改變圖片大小 -(UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize {// Create a graphics image contextUIGraphicsBeginImageContext(newSize);// Tell the old image to draw in this new context, with the desired// new size[image drawInRect:CG…

06-對圖像進行腐蝕操作

形態學中的腐蝕操作一般處理的圖像數據為二值的 cv2.erode(img,kernel,iterations 1) kernel表示拿多大的卷積核去腐蝕 iterations表示迭代次數 可以將一些帶有毛毛的圖像去毛毛化 原圖 import cv2 import numpy as npdef show_photo(name,picture):cv2.imshow(name,picture)…

Java BufferedReader skip()方法與示例

BufferedReader類skip()方法 (BufferedReader Class skip() method) skip() method is available in java.io package. skip()方法在java.io包中可用。 skip() method is used to skip the given number of bytes of characters (n_bytes_of_char) from this BufferedReader. s…

mysql gtid binlog_MySQL之-四步實現BinLog Replication升級為GTIDs Replication的代碼實例

1、將Master和Slave服務器都設置為read-onlymysql>SET global.read_onlyON;2、將Master與Slave服務器都停下來service mysql stop3、開啟GTIDs開啟GTIDs需要在master和slave服務器上都配置gtid-mode,log-bin,log-slave-updates,enforce-gtid-consistency(在MySQL 5.6.9之前是…

【記】瑣碎

1.GIF載入問題:http://www.cnblogs.com/Lewis/archive/2011/01/17/1937066.html 2.正則分段數字: "12345678945612456".replace(new RegExp((\\d)(?(\\d{3})$),ig),"$1,") 其中用到了正則的后則判斷? 3.給legend設定寬度 發現IE下可以 火狐下…

spring對事務的控制 AOP

我解釋一下(* com.evan.crm.service.*.*(..))中幾個通配符的含義: |第一個 * —— 通配 任意返回值類型| |第二個 * —— 通配 包com.evan.crm.service下的任意class| |第三個 * —— 通配 包com.evan.crm.service下的任意class的任意方法| |第四個 .. —— 通配 方…

Opencv實現利用滑動條來調整閾值

#include <opencv2/opencv.hpp> #include <iostream>using namespace cv; using namespace std; #define WINDOW_NAME "【程序窗口】" //為窗口標題定義的宏 //*--------------------------【練習】利用滑動條來調整閾值-----------------------------…

07-對圖像進行膨脹操作

形態學中的膨脹操作即讓照片變得更大&#xff0c;與腐蝕操作互為逆運算 cv2.dilate(erosion,kernel,iterations 1) 第一個參數&#xff1a;圖像對象名稱 第二個參數&#xff1a;卷積核的大小 第三個參數&#xff1a;迭代次數 此時就可與腐蝕操作進行相結合&#xff0c;腐蝕去毛…

Java LocalDate類| parse()方法與示例

LocalDate類parse()方法 (LocalDate Class parse() method) Syntax: 句法&#xff1a; public static LocalDate parse(CharSequence c_seq);public static LocalDate parse(CharSequence c_seq, DateTimeFormatter fmtr);parse() method is available in java.time package. …

Xhtml學習筆記

1. XHTML 是什么&#xff1f; XHTML 指可擴展超文本標簽語言&#xff08;EXtensible HyperText Markup Language&#xff09;。 XHTML 的目標是取代 HTML。 XHTML 與 HTML 4.01 幾乎是相同的。 XHTML 是更嚴格更純凈的 HTML 版本。 XHTML 是作為一種 XML 應用被重新定義的 HTML…

08-開運算和閉運算

開運算和閉運算實則就是將腐蝕操作和膨脹操作結合而已&#xff0c;也就是個先后循序罷了 開運算&#xff1a;先腐蝕再膨脹 閉運算&#xff1a;先膨脹再腐蝕 cv2.morphologyEx(img_open,cv2.MORPH_OPEN,kernel) cv2.morphologyEx(img_close,cv2.MORPH_CLOSE,kernel) 第一個參數…

連通域標記——實現硬幣自動計件

前言 在自動計算圖像中有幾枚硬幣的任務中&#xff0c;分離出前景和背景后是否就可以馬上實現自動計件&#xff0c;如果可以&#xff0c;如何實現&#xff1f;如果不可以&#xff0c;為什么&#xff1f; 答案是否定的。二值化之后我們的得到的只是前景總像素的多少&#xff0c…