Java虚拟机|JVM知识点汇总及简述->性能监控与调优
性能監控與調優
- 前言
這里學完整章后選擇一到兩個工具使用熟練,個人推薦Visual VM和Arthas搭配熟練使用
一、概述
1.性能評價/測試指標
1.1 停頓時間(響應時間)
- 提交請求和返回該請求的響應之間使用的時間,一般比較關注平均響應時間常用操作的響應時間列表:
- 在垃圾回收環節中,暫停時間:執行垃圾收集時,程序的工作線程被暫停的時間。
1.2 吞吐量
-
對單位時間內完成的工作量(請求)的量度
-
在GC中:運行用戶代碼的時間占總運行時間的比例(總運行時間:程序的運行時間+內存回收的時間)吞吐量為1-1/(1+n)。
-XX:GCTimeRatio=n
1.3 并發數
同—時刻,對服務器有實際交互的請求數
1.4 內存占用
Java堆區所占的內存大小
1.5 相互間的關系
這里主要討論停頓時間、吞吐量、并發數之間的關系,當吞吐量越高,并發數也就也高,而停頓時間就越短
二、JVM監控及診斷工具-命令行
1.概述
使用數據說明問題,使用知識分析問題,使用工具處理問題。無監控、不調優!
2.jps:查看正在運行的Java進程
- 說明
Java process status,顯示指定系統內所有的HotSpot虛擬機進程(查看虛擬機進程信息),可用于查詢正在運行的虛擬機進程。
說明:對于本地虛擬機進程來說,進程的本地虛擬機ID與操作系統的進程ID是一致的,是唯一的。
- options參數:
參數說明:
-q:僅僅顯示LVMID (local virtual machine id),即本地虛擬機唯一id。不顯示主類的名稱等
-l:輸出應用程序主類的全類名或如果進程執行的是jar包,則輸出jar完整路徑
-m:輸出虛擬機進程啟動時傳遞給主類main()的參數
-v:列出虛擬機進程啟動時的JVM參數。比如:-Xms20m -Xmx50m是啟動程序指定的jvm參數。
- 注意:
如果某Java進程關閉了默認開啟的UsePerfData參數(即使用參數-XX:-UsePerfData),那么jps命令(以及下面介紹的jstat)將無法探知該Java進程。
3.jstat:查看JVM的統計信息
- 說明
-
JVM Statistics Monitoring Tool:用于監視虛擬機各種運行狀態信息的命令行工具。它可以顯示本地或者遠程虛擬機進程中的類裝載、內存、垃圾收集、IT編譯等運行數據。
-
在沒有GUI圖形界面,只提供了純文本控制臺環境的服務器上,它將是運行期定位虛擬機性能問題的首選工具。常用于檢測垃圾回收問題以及內存泄漏問題。
3.1 option參數
- 類裝載相關的
-class:顯示ClassLoader的相關信息:類的裝載、卸載數量、總空間、類裝載所消耗的時間等
- 垃圾相關的
- JIT相關的
3.2 其他參數
- interval參數
用于指定輸出統計數據的周期,單位為毫秒。即:查詢間隔
-
count參數
用于指定查詢的總次數,跟在interval參數后面配合使用
-
-t參數
可以在輸出信息加上一個TimeStamp列,來顯示程序自打開運行的時間,單位:秒
可以根據-t參數來判斷是否要出現OOM:比較Java進程的啟動時間以及總GC時間(GCT列),或者兩次測量的間隔時間以及總GC時間的增量,來得出 GC時間占運行時間的比例。如果該比例超過20%,則說明目前堆的壓力較大;如果該比例超過90%,則悅明堆里幾乎沒有可用空間,隨時都可能拋出 OOM異常。
- -h參數
可以在周期性數據輸出時,輸出多少行數據后輸出一個表頭信息
3.3 如何通過jstat判斷內存泄露
分別為兩步:
4.jinfo:實時查看和修改JVM配置參數
- 說明
Configuration Info for Java,在很多情況下,Java應用程序不會指定所有的Java虛擬機參數。而此時,開發人員可能不知道某一個具體的Java虛擬機參數的默認值。在這種情況下,可能需要通過查找文檔獲取某個參數的默認值。這個查找過程可能是非常艱難的。但有了jinfo工具,開發人員可以很方便地找到Java虛擬機參數的當前值。
4.1 option參數
基本使用語法:jinfo [ options ] pid
注意:標記為manageable的參數非常有限
4.2 拓展參數
-
java -XX:+PrintFlagsInitial
查看所有JVM參數啟動的初始值
-
java -xx:+PrintFlagsFinal
查看所有JVM參數的最終值
-
java -XX:+ PrintCommandLineFlags
查看那些已經被用戶或者JVM設置過的詳細的XX參數的名稱和值
5.jmap:導出內存映像文件&內存使用情況
- 說明:
JVM Memory Map:作用一方面是獲取dump文件(堆轉儲快照文件,二進制文件),它還可以獲取目標Java進程的內存相關信息,包括Java堆各區域的使用情況、堆中對象的統計信息、類加載信息等。
5.1 option參數
基本語法:
- jmap [option] <pid>
- jmap [option] <executable> <core>
- jmap [option] [server_id@] <remote server IP or hostname>
5.2 兩種用法詳解
-
手動方式:
jmap -dump:live, format=b,file=d:\4.hprof pid
說明:live參數表示只打印內存的存活對象(往往出現OOM的時候就是太多存貨對象回收不了導致的,沒有該參數就表示打印全部對象),format參數標識打印的文件格式可以被監控工具識別,file就是指定文件生成位置,文件名后綴為 .hprof ,pid為進程號
-
自動方式:
-XX:+HeapDumpOnoutOfMemoryError:在程序發生OOM時,導出應用程序的當前堆快照。
-XX:HeapDumpPath:可以指定堆快照的保存位置。
說明:當程序發生OOM退出系統時,一些瞬時信息都隨著程序的終止而消失,而重現OOM問題往往比較困難或者耗時。此時若能在OOM時,自動導出dump文件就顯得非常迫切。
說明:這兩個參數都是對于內存某一個時刻進行的時間點信息,無法做到持續監控
- -jmap -heap pid
- -jmap -histo pid
5.3 小結
由于jmap將訪問堆中的所有對象,為了保證在此過程中不被應用線程干擾,jmap需要借助安全點機制,讓所有線程停留在不改變堆中數據的狀態。與前面講的jstat則不同,垃圾回收器會主動將jstat所需要的摘要數據保存至固定位置之中,而jstat只需直接讀取即可。
- 缺點:
- 由jmap導出的堆快照必定是安全點位置的。這可能導致基于該堆快照的分析結果存在偏差。
- 加入生命周期只在兩個安全點之間有效,jmap記錄的時候是檢測不到的
- 如果某個線程長時間無法跑到安全點,jmap將一直等下去。
6.jhat:JDK自帶堆分析工具
- 概述
JVM Heap Analysis Tool,jhat內置了一個微型的HTTP/HTML服務器,生成dump文件的分析結果后,用戶可以在瀏覽器中查看分析結果(分析虛擬機轉儲快照信息)。使用了jhat命令,就啟動了一個http服務,端口是7000,即http://localhost:7000/,就可以在瀏覽器里分析。
- 注意
jhat命令在JDK9、JDK10中已經被刪除,官方建議用VisualVM代替。所以這里就不做過多介紹
7.jstack:打印JVM中的線程快照
- 概述
JVM Stack Trance打印當前進程的所有線程
- 作用
生成線程快照的作用:可用于定位線程出現長時間停頓的原因,如線程間死鎖、死循環、請求外部資源導致的長時間等待等問題。這些都是導致線程長時間停頓的常見原因。當線程出現停頓時,就可以用jstack顯示各個線程調用的堆棧情況。
- 快照中需要注意的地方
- 死鎖,Deadlock(重點關注)
- 等待資源,waiting on condition(重點關注)
- 等待獲取監視器,waiting on monitor entry(重點關注)阻塞,Blocked(重點關注)
- 執行中,Runnable
- 暫停,Suspended
7.1 option參數
- -F:當正常輸出的請求不被響應時,強制輸出線程堆棧
- -l:除堆棧外,顯示關于鎖的附加信息
- -m:如果調用到本地方法的話,可以顯示C/C++的堆棧
- -h:幫助操作
8.jcmd:多功能命令行
- 概述
它是一個多功能的工具,可以用來實現前面除了jstat之外所有命令的功能。比如:用它來導出堆、內存使用、查看Java進程、導出線程信息、執行GC、JVM運行時間等。官方推薦使用jcmd代替jmap
8.1 基本語法
- jcmd -l:列出所有的JVM進程
- jcmd pid help:針對指定的進程,列出支持的所有命令
- jcmd pid具體命令團:顯示指定進程的指令命令的數據
三、JVM監控及診斷工具-GUI
1.工具概述
- 使用命令行工具的弊端
- 工具分類
-
JDK自帶的工具:jConsole、Visual VM、JMC(Java mission control)
-
第三方工具:MAT(Eclipse)、JProfiler、Arthas、Btrace
2.jConsole
2.1 概述
-
從JDK5開始,在JDK中自帶的java監控和管理控制臺。
-
用于對VM中內存、線程和類等的監控,是一個基于JMX(java management extensions)的GUI性能監控工具
- 位置:
在JDK目錄下的bin目錄可找到
3.Visual VM
3.1 概述
- Visual VM是一個功能強大的多合一故障診斷和性能監控的可視化工具。
- 它集成了多個JDK命令行工具,使用Visual M可用于顯示虛擬機進程及進程的配置和環境信息(jps,jinfo),監視應用程序的CPU、GC、堆、方法區及線程的信息(jstat、jstack)等,代替JConsole。
- 在JDK 6 Update 7以后,Visual VM便作為DK的一部分發布(VisualVM在JDK/bin目錄下),是完全免費的
- Visual VM也可以作為獨立的軟件安裝
- 安裝方式
-
在JDK的bin目錄下,如果沒有則自行下載
-
可在idea中下載啟動Visual 的插件,記得要配置.exe文件和JDK的home目錄
-
插件安裝可在官網或客戶端中下載(強烈推薦Visual GC這個插件)
3.2 主要功能
生成/讀取堆內存快照
查看JVM參數和系統屬性
查看運行中的虛擬機進程
生成/讀取線程快照
程序資源的實時監控
其他功能
JMX代理連接、遠程環境監控、CPU分析和內存分析
4.MAT
4.1 概述
MAT(Memory Analyzer Tool)工具是一款功能強大的Java堆內存分析器。**主要用于dump文件的分析可以用于查找內存泄漏以及查看內存消耗情況。**MAT是基于Eclipse開發的,不僅可以單獨使用,還可以作為插件的形式嵌入在Eclipse中使用。是免費軟件
4.2 dump文件信息
- 內容
MAT可以分析heap dump文件。在進行內存分析時,只要獲得了反映當前設備內存映像的hprof文件,通過MAT打開就可以直觀地看到當前的內存信息。一般說來,這些內存信息包含:
- 所有的對象信息,包括對象實例、成員變量、存儲于棧中的基本類型值和存儲于堆中的其他對象的
引用值。 - 所有的類信息,包括classloader、類名稱、父類、靜態變量等. GCRoot到所有的這些對象的引用路徑
- 線程信息,包括線程的調用棧及此線程的線程局部變量(TLS)
- 優點
能夠快速為開發人員生成內存泄漏報表,方便定位問題和分析問題
- 導出dump文件方式
- 可以在visual vm里面生成
- 在第5節imap參數中,直接用imap參數導出
- 有兩個參數可以導出dump文件-XX:+HeapDumpOnoutOfMemoryError:在程序發生OOM時,導出應用程序的當前堆快照。-XX:HeapDumpPath:可以指定堆快照的保存位置。
- 當然也可以直接用MAT生成dump文件,前提要知道進程號
4.3 分析MAT中的dump文件過程
- histogram
展示了各個類的實例數目以及這些實例的Shallowheap 或Retainedheap的總和
- thread overview
查看系統中的Java線程、查看局部變量的信息
-
獲得對象相互引用的關系
with outgoing references:查看這個對象引用了誰
with incoming references:查看誰引用了這個對象
?
4.4 深堆和淺堆
- 淺堆(Shallow Heap)
淺堆是指一個對象所消耗的內存。在32位系統中,一個對象引用會占據4個字節,一個int類型會占據4個字節,long型變量會占據8個字節,每個對象頭需要占用8個字節。根據堆快照格式不同,對象的大小可能會向8字節進行對齊。以String為例: 2個int值共占8字節,對象引用占用4字節,對象頭8字節,合計20字節,向8字節對齊,故占24字節。(jdk7中)。
注意:與value值的多少是無關的
- 保留集(Retained Set)
對象A的保留集指當對象A被垃圾回收后,可以被釋放的所有的對象集合(包括對象A本身),即對象A的保留集可以被認為是只能通過對象A被直接或間接訪問到的所有對象的集合。通俗地說,就是指僅被對象A所持有的對象的集合。
- 深堆(Retained Heap)
就是自己的淺堆大小加上保留集的大小就是深堆的大小
- 對象實際大小
對象的實際大小就是指:淺堆大小+自己能夠引用的全部對象大小
- 案例分析
代碼:
public class StudentTrace {static List<WebPage> webpages = new ArrayList<>();public static void createWebPages() {for (int i = 0; i < 100; i++) {WebPage wp = new WebPage();wp.setUrl( "http://www." + Integer.toString(i) + ".com" );wp.setContent( Integer.toString(i));webpages.add(wp);}}public static void main(String[] args) {createWebPages();Student s3 = new Student(3,"LLL");Student s5 = new Student(5,"HHH");Student s7 = new Student(7,"JJJ");for (int i = 0; i < webpages.size(); i++) {if (i % s3.getId() == 0)s3.visit(webpages.get(i));if (i %s5.getId( ) == 0)s5.visit(webpages.get(i));if (i %s7.getId( ) == 0)s7.visit(webpages.get(i));}webpages.clear();System.gc();} }class Student{private int id;private String name;private List<WebPage> history = new ArrayList<>();public Student(int id, String name) {this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<WebPage> getHistory() {return history;}public void setHistory(List<WebPage> history) {this.history = history;}public void visit(WebPage wp){if(wp != null){history.add(wp);}} }class WebPage{private String url;private String content;public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getContent() {return content;}public void setContent(String content) {this.content = content;} }分析7號JJJ對象的內存占用
- 考慮JJJ同學:15個 webpage,每個對應152個字節 15* 152= 2280字節,即為elementData的實際大小
- 能被7整除,且能被3整除,以及能被7整除,且能被5整除的數值有:0,21,42,63,84,35,70 共7個數。7*152 = 1064字節,2280 -1064 +72 = 1288字節
- 72個字節組成為:15個elementData的元素*4字節 =60字節,60+8個對象頭的字節數+4字節=72字節
4.5 支配樹
- 概述
MAT提供了一個稱為支配樹(Dominator Tree)的對象圖。支配樹體現了對象實例間的支配關系。**在對象引用圖中,所有指向對象B的路徑都經過對象A,則認為對象A支配對象B。如果對象A是離對象B最近的一個支配對象,則認為對象A為對象B的直接支配者。**支配樹是基于社象間的引用圖所建立的,它有以下基本性質:
- 對象A的子樹(所有被對象A支配的對象集合)表示對象A的保留集(retained set),即深堆。
- 如果對象A支配對象B,那么對象A的直接支配者也支配對象B。
- 支配樹的邊與對象引用圖的邊不直接對應。
- 圖示
四、再談內存泄露
1.內存泄露的理解與分類
- 概述
可達性分析算法來判斷對象是否是不再使用的對象,本質都是判斷一個對象是否還被引用。那么對于這種情況下,由于代碼的實現不同就會出現很多種內存泄漏問題(讓JVM誤以為此對象還在引用中,無法回收,造成內存泄漏)。
1.1 內存泄漏與內存溢出的關系
內存泄漏(Memory Leak):
申請了內存用完了不釋放,比如一共有1024M 的內存,分配了512M的內存一直不回收,那么可以用的內存只有521M 了,仿佛泄露掉了一部分。
內存溢出(Out Of Memory):
申請內存時,沒有足夠的內存可以使用。
可見,內存泄漏和內存溢出的關系:內存泄漏的增多,最終會導致內存溢出。
1.2 內存泄漏的分類
- 經常發生:發生內存泄露的代碼會被多次執行,每次執行,泄露一塊內存;
- 偶然發生:在某些特定情況下才會發生;
- 一次性:發生內存泄露的方法只會執行一次;
- 隱式泄漏:一直占著內存不釋放,直到執行結束;嚴格的說這個不算內存泄漏,因為最終釋放掉了,但是如果執行時間特別長,也可能會導致內存耗盡。
2.Java中內存泄漏的8種情況
2.1 靜態集合類
靜態集合類,如HashMap、LinkedList等等。如果這些容器為靜態的,那么它們的生命周期與JVM程序一致,則容器中的對象在程序結束之前將不能被釋放,從而造成內存泄漏。簡單而言,長生命周期的對象持有短生命周期對象的引用,盡管短生命周期的對象不再使用,但是因為長生命周期對象持有它的引用而導致不能被回收。
public class test01(){static List list = new ArrayList();public void oomTest(){Object o = new Object();//局部變量list.add(o);} }2.2 單例模式
單例模式,和靜態集合導致內存泄露的原因類似,因為單例的靜態特性,它的生命周期和JVM 的生命周期一樣長,所以如果單例對象如果持有外部對象的引用,那么這個外部對象也不會被回收,那么就會造成內存泄漏。
2.3 內部類持有外部類
內部類持有外部類,如果一個外部類的實例對象的方法返回了一個內部類的實例對象。
這個內部類對象被長期引用了,即使那個外部類實例對象不再被使用,但由于內部類持有外部類的實例對象,這個外部類對象將不會被垃圾回收,這也會造成內存泄漏。
2.4 各種連接,數據庫連接、網絡連接和IO連接等
在對數據庫進行操作的過程中,首先需要建立與數據庫的連接,當不再使用時,需要調用close方法來釋放與數據庫的連接。只有連接被關閉后,垃圾回收器才會回收對應的對象。
否則,如果在訪問數據庫的過程中,對Connection、Statement或ResultSet不顯性地關閉,將會造成大量的對象無法被回收,從而引起內存泄漏。
2.5 變量不合理作用域
變量不合理的作用域。一般而言,一個變量的定義的作用范圍大于其使用范圍,很有可能會造成內存泄漏。另一方面,如果沒有及時地把對象設置為null,很有可能導致內存泄漏的發生。
public class UsingRandom {private String msg;public void receiveMsg(){readFromNet();//從網絡中接受數據保存到msg中saveDB();//把msg保存到數據庫中} } //如上面這個偽代碼,通過readFromNet方法把接受的消息保存在變量 //msg中,然后調用saveDB方法把msg的內容保存到數據庫中, //此時msg已經就沒用了,由于msg的生命周期與對象的生命周期相同, //此時msg還不能回收,因此造成了內存泄漏。 //實際上這個msg變量可以放在receiveMsg方法內部,當方法使用完, //那么msg的生命周期也就結束,此時就可以回收了。還有一種方法, //在使用完msg后,把msg設置為null, //這樣垃圾回收器也會回收msg的內存空間。2.6 改變哈希值
改變哈希值,當一個對象被存儲進HashSet集合中以后,就不能修改這個對象中的那些參與計算哈希值的字段了。
否則,對象修改后的哈希值與最初存儲進HashSet集合中時的哈希值就不同了,在這種情況下,即使在contains方法使用該對象的當前引用作為的參數去HashSet集合中檢索對象,也將返回找不到對象的結果,這也會導致無法從HashSet集合中單獨刪除當前對象,造成內存泄漏。
這也是String為什么被設置成了不可變類型,我們可以放心地把String存入 HashSet,或者把String 當做HashMap的key 值;
2.7 緩存泄漏
內存泄漏的另一個常見來源是緩存,一旦你把對象引用放入到緩存中,他就很容易遺忘。比如:之前項目在一次上線的時候,應用啟動奇慢直到夯死,就是因為代碼中會加載一個表中的數據到緩存(內存)中,測試環境只有幾百條數據,但是生產環境有幾百萬的數據。
對于這個問題,可以使用WeakHashMap(軟引用)代表緩存,此種Map的特點是,當除了自身有對key的引用外,此key沒有其他引用那么此map會自動丟棄此值。
2.8 監聽器和回調
內存泄漏另一個常見來源是監聽器和其他回調,如果客戶端在你實現的API中注冊回調,卻沒有顯示的取消,那么就會積聚。
需要確保回調立即被當作垃圾回收的最佳方法是只保存它的弱引用,例如將他們保存成為weakHashMap中的鍵。
3.內存泄漏案例分析
3.1 案例一
public class MyStack {private Object[] elements;private int size = 0;private static final int DEFAULT_INITIAL_CAPACITY = 16;public MyStack() {elements = new Object[DEFAULT_INITIAL_CAPACITY];}//壓棧操作public void push(Object e) {ensureCapacity();elements[size++] = e;}//這個出棧操作是錯誤的,我們只是把想要刪除的指針引用向下面移了,被刪除的對象還占著空間/*public Object pop(){if (size == 0)throw new EmptyStackException();return elements[ --size];}*///這樣就可以了,讓被刪除的對象的值置為nullpublic Object pop(){if(size == 0){throw new EmptyStackException();}Object o = elements[--size];elements[size] = null; //size已經減過了return o;}private void ensureCapacity() {if (elements.length == size)elements = Arrays.copyOf(elements,2 * size + 1);}}3.2 案例二
public class TestActivity extends Activity{private static final Object key = new Object();@Overrideprotected void onCreate( Bundle savedInstanceState) {super.onCreate( savedInstanceState) ;setContentview(R.layout.activity_main);new Thread(){//匿名線程public void run() {synchronized (key) {try {key.wait();}catch (InterruptedException e) {e. printstackTrace();}}}}.start();} }- 出現的問題
匿名線程始終不能被GC
- 解決辦法
五、OQL語言查詢對象信息
- 概述
MAT支持一種類似于SQL的查詢語言OQL (Object Query Language)。OQL使用類SQL語法,可以在堆中進行對象的查找和篩選。
1.SELECT子句
在MAT中,Select子句的格式與SQL基本一致,用于指定要顯示的列。Select子句中可以使用“*”,查看結果對象的引用實例(相當于outgoing references)。
-
使用“OB3ECTS”關鍵字,可以將返回結果集中的項以對象的形式顯示。
SELECT objects v.elementData FROM java.util.Vector v
SELECT OBECTS s.value FROM java.lang.string s
-
在Select子句中,使用“AS RETAINED SET”關鍵字可以得到所得對象的保留集。
SELECT AS RETAINED SET * FROM com.atguigu.mat. Student
-
“DISTINCT”關鍵字用于在結果集中去除重復對象。
SELECT DISTINCT OBECTS classof(s)FROM java.lang.String s
2.FROM子句
-
From子句用于指定查詢范圍,它可以指定類名、正則表達式或者對象地址。
SELECT * FROM java.lang.String s
-
下例使用正則表達式,限定搜索范圍,輸出所有com.atguigu包下所有類的實例
SELECT FROM "com.atguigul…”
-
也可以直接使用類的地址進行搜索。使用類的地址的好處是可以區分被不同ClassLoader加載的同一種類型。
select * from 0x37a0b4d
3.WHERE子句
where子句用于指定oQL的查詢條件。oQL查詢將只返回滿足where子句指定條件的對象。Where子句的格式與傳統SQL極為相似。
- 下例返回長度大于10的char數組。
SELECT * FROM char[] s WHERE s.@length>10 - 下例返回包含“java”子字符串的所有字符串,使用“LIKE”操作符,“LIKE”操作符的操作參數為正則表達式。
SELECT * FROM java.lang.String s WHERE toString(s)LIKE “.java.” - 下例返回所有value域不為null的字符串,使用“=”操作符。
SELECT * FROM java.lang.String s where s.value !=null - where子句支持多個條件的AND、OR運算。下例返回數組長度大于15,并且深堆大于1000字節的所有Vector對象。
SELECT * FROM java.util.Vector v WHERE v.elementData.@length>15 AN Dv.@retainedHeapsize>1000
4.內置對象與方法
0QL中可以訪問堆內對象的屬性,也可以訪問堆內代理對象的屬性。訪問堆內對象的屬性時,格式如下:
[ <alias>. ] <field> . <field>. <field>其中alias為對象名稱。
-
訪問java.io.File對象的path屬性,并進一步訪問path的value屬性:
SELECT toString(f.path.value)FROM java.io.File f
-
下例顯示了String對象的內容、objectid和objectAddress。
SELECT s.toString(), s.@objectId, s.@objectAddress FROMjava.lang.String s -
下例顯示java.util.Vector內部數組的長度。
SELECT v.elementData.@length FROM java.util.Vector v -
下例顯示了所有的java.util.Vector對象及其子類型
select * from INSTANCEOF java.util.Vector
六、JProfiler
1.基本概述
想要用一款集成在idea的分析工具,或想要比mat工具更加全面,JProfiler由此誕生,是一款Java應用性能診斷工具,功能強大,但注意是收費的
1.1 特點
- 使用方便、界面操作友好―(簡單且強大)
- 對被分析的應用影響小(提供模板)
- CPU, Thread ,Memory分析功能尤其強大
- 支持對jdbc ,nosql,jsp, servlet, socket等進行分析
- 支持多種模式(離線,在線)的分析
- 支持監控本地、遠程的JVM
- 跨平臺,擁有多種操作系統的安裝版本
1.2 主要功能
2.具體使用
2.1 數據采集方式
- Instrumentation(重構模式):這是JProfiler全功能模式。在class加載之前,JProfier把相關功能代碼寫入到需要分析的class的bytecode中,對正在運行的jvm有一定影響。
- 優點:功能強大。在此設置中,調用堆棧信息是準確的。
- 缺點:若要分析的class較多,則對應用的性能影響較大,CPU開銷可能很高(取決于Filter的控制)。因此使用此模式一般配合Filter使用,只對特定的類或包進行分析。
-
Full sampling(抽樣模式):類似于樣本統計,每隔一定時間(5ms )將每個線程棧中方法棧中的信息統計出來。
- 優點:對[PU的開銷非常低,對應用影響小(即使你不配置任何Filter)
- 缺點:一些數據/特性不能提供(例如:方法的調用次數、執行時間)
2.2 各種重要功能
這里這些功能演示及案例分析就不扣字寫了,大家想要了解請去尚硅谷看JVM視頻(343~349)
- 遙感監測(Telemetries)
- 內存視圖(Live Memory)
- 堆遍歷(heap walker)
- cpu視圖(cpu views)
- 線程視圖(threads)
- 監視器&鎖(Monitors&locks)
七、Arthas
1.前奏
1.1 JProfiler與JvisualVM的缺點
這兩款工具有個缺點,都必須在服務端項目進程中配置相關的監控參數。然后工具通過遠程連接到項目進程,獲取相關的數據。這樣就會帶來一些不便,比如線上環境的網絡是隔離的,本地的監控工具根本連不上線上環境。并且類似于Jprofiler這樣的商業工具,是需要付費的。
1.2 概述
Arthas(阿爾薩斯)是Alibaba開源的Java診斷工具,在線排查問題,無需重啟;動態跟蹤Java代碼;實時監控JVM狀態。Arthas支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同時提供豐富的Tab自動補全功能,進一步方便進行問題的定位和診斷。借鑒并基于很多優秀的軟件組合而成的一個工具
- 注意:
由于是開源的項目且是國人開發,這里就不做過多介紹,大家可移步至官網查看中文文檔https://arthas.aliyun.com/doc/,里面有十分詳細的說明
八、JMC(Java Mission Control)
1.概述
是oracle公司自己的工具,在JDK的bin目錄下找到jmc.exe可執行文件
九、其他調優工具
- Tprofiler:是由阿里開源的一款尋找錯誤熱點代碼的工具
- Btrace:簡潔明了,大意是一個Java平臺的安全的動態追蹤工具。可以用來動態地追蹤一個運行的Java程序。BTrace動態調整目標應用程序的類以注入跟蹤代碼(“字節碼跟蹤”)。
- YourKit
- JProbe
- Spring Insight
總結
以上是生活随笔為你收集整理的Java虚拟机|JVM知识点汇总及简述->性能监控与调优的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mac 字体微软雅黑字体_在Micros
- 下一篇: java美元兑换,(Java实现) 美元