Jvm常用的命令行工具(二)

接上篇,本文繼續學習其它的JDK工具
## 4.jmap :Java內存映像工具(Memory Map for Java)

jmap 命令用於生成堆轉儲快照(heapdump 或者dump文件),如果不適用jmap工具,通常要想獲取Java堆轉儲快照, 需要使用一些比較“暴力”得手段,比如在vm args中使用:**-XX:+HeapDumpOnOutOfMemoryError**參數,可以在虛擬機OOM異常出現之後自動生成dump文件,通過-XX:+HeapDumpOnCtrlBreak參數則可以使用[Ctrl]+[Break]鍵讓虛擬機生成dump文件,或者在Linux中通過kill -3命令發送進程退出信號“嚇唬”一下虛擬機,也能拿到dump文件。

jmap得作用不僅僅是爲了獲取dump文件,它還可以查詢finalize執行隊列、Java堆和永久代得詳細信息,如空間使用率、當前使用得哪種收集器等。

jmap在Windows平臺下也有很多功能是受限得,除了生成dump文件得-dump選項和用於查看每個類得實例、空間佔用統計得-histo選項,其他參數都只能在linux/solaris下使用

#### jmap命令格式
```
jmap [option] vmid
```
選項 | 作用
-- | --
-dump | 生成Java堆轉儲快照,格式爲:-dump:[live,]format=b,file=<filename>,其中live子參數說明是否只dump出存活的對象
-finalizeinfo | 顯示在F-Queue中等待Finalizer線程執行finalize方法的對象
-heap | 顯示Java堆詳細信息,如使用哪種回收器、參數配置、分代狀況等
-histo | 顯示堆中對象統計信息,包括類、實例數量、合計容量
-permstat | 以ClassLoader 爲統計口徑顯示永久代內存狀態 jdk1.7
-F | 當虛擬機進程對-dump選項沒有響應時,可使用這個選項強制生成dump快照

例子:
```
[root@VM_0_13_centos ~]# jmap -dump:format=b,file=eladmin.bin 32534
Dumping heap to /root/eladmin.bin ...
Heap dump file created


[root@VM_0_13_centos ~]# jmap -finalizerinfo 32534
Attaching to process ID 32534, please wait...
Debugger attached successfully.
Client compiler detected.
JVM version is 25.201-b09
Number of objects pending for finalization: 0


[root@VM_0_13_centos ~]# jmap -heap 32534
Attaching to process ID 32534, please wait...
Debugger attached successfully.
Client compiler detected.
JVM version is 25.201-b09

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 268435456 (256.0MB)

[root@VM_0_13_centos ~]# jmap -histo 32534
省略。。。。。。
6725:             1              8  sun.util.locale.provider.CalendarDataUtility$CalendarWeekParameterGetter
6726:             1              8  sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter
6727:             1              8  sun.util.resources.LocaleData$LocaleDataResourceBundleControl

```

## 5. jhat:虛擬機堆轉儲快照分析工具(JVM Heap Analysis Tool)
一般jhat命令與jmap命令搭配使用,通過jhat分析jmap生成的堆轉儲快照,jhat 內置了一個微型的HTTP/HTML服務器,生成dump文件的分析結果後,可以通過瀏覽器來查看。

但一般在實際使用中,除非沒有其他工具可以,一般沒人用這個,原因有二:
- 一是一般不會在部署應用程序的服務器上直接分析dump文件,即使可以這樣做,也會盡量將dump文件複製到其他機器上分析,比如拷貝到我們本地進行分析,因爲分析工作時一個耗時而且消耗硬件資源的過程,既然都要在其他機器上進行了,就米有必要收到命令行工具的限制了;
- 另一個原因時jhat的分析功能相對來說比較簡陋,後文會介紹到VisualVM以及專業分析dump文件的工具,都會更加強大而專業。

例子:
```
[root@VM_0_13_centos ~]# jhat eladmin.bin 
Reading from eladmin.bin...
Dump file created Tue Dec 31 12:50:29 CST 2019
Snapshot read, resolving...
Resolving 1556642 objects...
Chasing references, expect 311 dots.......................................................................................................................................................................................................................................................................................................................
Eliminating duplicate references.......................................................................................................................................................................................................................................................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

```
屏幕顯示“Service is ready”後,在瀏覽器輸入http://host:7000/就可以看到分析結果。![image](62E6E0B49418409AB3E7466BDFE7B6A7)

分析結果默認是以包爲單位進行分組顯示,分析內存泄漏問題主要會使用到其中的“Heap Histogram”與OQL頁籤的功能,前者可以找到內存中總容量最大的對象,後者是標準的對象查詢語言,使用類似的SQL語法對內存中的對象進行查詢統計。

## 6. jstack : Java堆棧跟蹤工具(Stack Trace for Java) 

jstack 命令用於生成虛擬機當前時刻的**線程快照(thread dump 或者java core文件)**。線程快照就是當前虛擬機內每一條線程正在執行的方法堆棧的集合,生成線程快照的主要目的是==定位線程出現長時間停頓的原因==,如線程死鎖、死循環、請求外部資源導致的長時間等待等都是導致線程長時間停頓的常見原因。線程出現停頓的時候通過jstack來查看各個線程的調用堆棧,就可以知道沒有響應的線程到底在後臺做了什麼事情,或者等待了什麼資源。

#### jstack 命令格式
```
jstack [option] vmid
```
選項 | 作用
-- | --
-F |當正常輸出的請求不被響應時,強制輸出線程堆棧
-l | 除堆棧外,顯示關於鎖的附加信息
-m | 如果調用到本地方法,可以顯示C/C++的堆棧

例子:
```
[root@VM_0_13_centos ~]# jstack -l 32534
2019-12-31 13:43:09
Full thread dump Java HotSpot(TM) Client VM (25.201-b09 mixed mode):

"Attach Listener" #167 daemon prio=9 os_prio=0 tid=0xdf4bb800 nid=0xed0 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"logback-9" #62 daemon prio=5 os_prio=0 tid=0xdf4d1800 nid=0x679 waiting on condition [0xde0ba000]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0xe9e94c18> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
    - None
[root@VM_0_13_centos ~]# jstack -F 32534
省略
```
> jdk 1.5中,java.lang.Thread類新增了一個getAllStackTraces()方法用於獲取虛擬機中所有線程的StackTraceElement對象。

Jprofiler:<https://blog.csdn.net/wytocsdn/article/details/79258247>

 

關於JVM與GC分析的工具先到這,後續根據我們的項目看能不能再搞一篇JVM 分析的實戰篇。

##### 附:
 疫情也不知道5月份能不能過去,最近面試大廠也只能視頻或者在線面試,難度大大提高,因爲要當場調試出編程題的結果,像我這種菜雞,面一次掛一次,我太難了,公司又快要從西二旗搬到亦莊去,留給同志們的時間不多了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章