常用的JDK自带命令行工具

标签: Virtual Machine JDK 工具 | 发表时间:2013-11-14 20:57 | 作者:四火
出处:http://www.raychase.net

文章系本人原创,转载请保持完整性并注明出自 《四火的唠叨》

常用的JDK自带命令行工具

在 这里可以找得到这些工具的列表,虽然官网上免责声明为 “The tools described in this section are unsupported and experimental in nature and should be used with that in mind. They might not be available in future JDK versions.”,但实际上这些工具还是非常有用的,尤其可以站在JVM的角度来定位问题。我在此简单罗列一些常用的工具和命令,以及相应的执行结果示例。如果你经常和JVM打交道,最好对这些工具的常用命令熟记。

 

jstat,这个工具很强大,可以监测Java虚拟机GC多方面的状态,具体参数含义参见 此链接:

./jstat -gc 84012 1000 3

S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT
2112.0 2112.0  0.0    0.0   17024.0    0.0     63872.0     1319.9   21248.0 4728.1 743416  209.646   5      0.046  209.692
2112.0 2112.0  0.0    0.0   17024.0    0.0     63872.0     1319.9   21248.0 4728.1 743849  209.755   5      0.046  209.801
2112.0 2112.0  0.0    0.0   17024.0    0.0     63872.0     1319.9   21248.0 4728.1 744282  209.864   5      0.046  209.910

 

jmap,这大概是最常用的命令。下面这个命令不但可以列出类的实例数量,还有强制进行一次full GC的“副作用”,这样的副作用对于定位某些问题很有帮助,参见 《使用堆外内存》:

./jmap -histo:live 84012

 num     #instances         #bytes  class name
----------------------------------------------
   1:           824        1177656  [B
   2:          8096        1106672
...

使用-heap参数,则可以打印堆的使用情况:

./jmap -heap 84012

Attaching to process ID 84012, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.65-b04-462

using parallel threads in the new generation.
using thread-local object allocation.
Concurrent Mark-Sweep GC

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 132120576 (126.0MB)
   NewSize          = 21757952 (20.75MB)
   MaxNewSize       = 174456832 (166.375MB)
   OldSize          = 65404928 (62.375MB)
   NewRatio         = 7
   SurvivorRatio    = 8
   PermSize         = 21757952 (20.75MB)
   MaxPermSize      = 85983232 (82.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 19595264 (18.6875MB)
   used     = 16785688 (16.008079528808594MB)
   free     = 2809576 (2.6794204711914062MB)
   85.66196403375837% used
Eden Space:
   capacity = 17432576 (16.625MB)
   used     = 16785688 (16.008079528808594MB)
   free     = 646888 (0.6169204711914062MB)
   96.28920017328477% used
From Space:
   capacity = 2162688 (2.0625MB)
   used     = 0 (0.0MB)
   free     = 2162688 (2.0625MB)
   0.0% used
To Space:
   capacity = 2162688 (2.0625MB)
   used     = 0 (0.0MB)
   free     = 2162688 (2.0625MB)
   0.0% used
concurrent mark-sweep generation:
   capacity = 65404928 (62.375MB)
   used     = 1390576 (1.3261566162109375MB)
   free     = 64014352 (61.04884338378906MB)
   2.126102791520541% used
Perm Generation:
   capacity = 21757952 (20.75MB)
   used     = 4852336 (4.6275482177734375MB)
   free     = 16905616 (16.122451782226562MB)
   22.301437194088855% used

使用-permstat参数,查看永久区:

./jmap -permstat 84012

Attaching to process ID 84012, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.65-b04-462
1239 intern Strings occupying 104312 bytes.
finding class loader instances ..Warning: skipping invalid TLAB for thread t@59779
Warning: skipping invalid TLAB for thread t@59527
Warning: skipping invalid TLAB for thread t@59907
Warning: skipping invalid TLAB for thread t@60163
Warning: skipping invalid TLAB for thread t@60419
Warning: skipping invalid TLAB for thread t@60675
Finding object size using Printezis bits and skipping over...
done.
computing per loader stat ..done.
please wait.. computing liveness...done.
class_loader	classes	bytes	parent_loader	alive?	type

	590	3973048	  null  	live
0x00000007f44cace0	0	0	  null  	live	sun/misc/Launcher$ExtClassLoader@0x00000007faff8a40
0x00000007f44c1478	8	143928	0x00000007f44cace0	live	sun/misc/Launcher$AppClassLoader@0x00000007fb056e88

total = 3	598	4116976	    N/A    	alive=3, dead=0	    N/A    

把内存中的堆dump成一个镜像文件:

./jmap -dump:live,format=b,file=/Users/xiongyi/Documents/dump.core 84012

 

jstack,线程堆栈打印。注意waiting to lock <xxx>在等待锁,比如进入临界区时;locked <xxx>表示当前同步操作,线程锁住了某资源;而waiting on <xxx>指的是在同步块内,wait方法的执行中暂时地释放了该锁的占用,等唤醒的时候需要重新获取:

./jstack 84012

2013-11-11 18:30:35
Full thread dump Java HotSpot(TM) 64-Bit Server VM (20.65-b04-462 mixed mode):

"Attach Listener" daemon prio=9 tid=7ff64e206800 nid=0x117782000 waiting on condition [00000000]
   java.lang.Thread.State: RUNNABLE

"Low Memory Detector" daemon prio=5 tid=7ff64c80f000 nid=0x117c96000 runnable [00000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" daemon prio=9 tid=7ff64c80e800 nid=0x117b93000 waiting on condition [00000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" daemon prio=9 tid=7ff64c80d800 nid=0x117a90000 waiting on condition [00000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=9 tid=7ff64c80d000 nid=0x11798d000 runnable [00000000]
   java.lang.Thread.State: RUNNABLE

"Surrogate Locker Thread (Concurrent GC)" daemon prio=5 tid=7ff64c80c000 nid=0x11788a000 waiting on condition [00000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=8 tid=7ff64e13d800 nid=0x11767f000 in Object.wait() [11767e000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <7f44c0ed0> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
	- locked <7f44c0ed0> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:171)

"Reference Handler" daemon prio=10 tid=7ff64e13c800 nid=0x11757c000 in Object.wait() [11757b000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <7f44c0018> (a java.lang.ref.Reference$Lock)
	at java.lang.Object.wait(Object.java:485)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
	- locked <7f44c0018> (a java.lang.ref.Reference$Lock)

"main" prio=5 tid=7ff64c800800 nid=0x10f709000 runnable [10f708000]
   java.lang.Thread.State: RUNNABLE
	at test.Test.main(Test.java:7)

"VM Thread" prio=9 tid=7ff64e138000 nid=0x117479000 runnable

"Gang worker#0 (Parallel GC Threads)" prio=9 tid=7ff64e000000 nid=0x112b0f000 runnable

"Gang worker#1 (Parallel GC Threads)" prio=9 tid=7ff64e001000 nid=0x112c12000 runnable

"Gang worker#2 (Parallel GC Threads)" prio=9 tid=7ff64e001800 nid=0x112d15000 runnable

"Gang worker#3 (Parallel GC Threads)" prio=9 tid=7ff64e002000 nid=0x112e18000 runnable

"Gang worker#4 (Parallel GC Threads)" prio=9 tid=7ff64e002800 nid=0x112f1b000 runnable

"Gang worker#5 (Parallel GC Threads)" prio=9 tid=7ff64e003800 nid=0x11301e000 runnable

"Gang worker#6 (Parallel GC Threads)" prio=9 tid=7ff64e004000 nid=0x113121000 runnable

"Gang worker#7 (Parallel GC Threads)" prio=9 tid=7ff64e004800 nid=0x113224000 runnable

"Concurrent Mark-Sweep GC Thread" prio=9 tid=7ff64e0e2000 nid=0x1170f0000 runnable
"Gang worker#0 (Parallel CMS Threads)" prio=9 tid=7ff64e0e0800 nid=0x1166ea000 runnable

"Gang worker#1 (Parallel CMS Threads)" prio=9 tid=7ff64e0e1800 nid=0x1167ed000 runnable

"VM Periodic Task Thread" prio=10 tid=7ff64c820800 nid=0x117d99000 waiting on condition

"Exception Catcher Thread" prio=10 tid=7ff64c801800 nid=0x10f936000 runnable
JNI global references: 963

 

jinfo,可以打印JVM执行的参数信息,有一个非常大的作用在于,部分JVM参数在执行过程中是可以修改的,请参见这篇 《通过jinfo工具在full GC前后做heap dump》,通过jinfo改变参数HeapDumpBeforeFullGC和HeapDumpAfterFullGC,输出heap dump后,再改回来。

 

jhat,可以比对core文件之间的对象变化,支持对象查询语言(OQL),请参见 这里。

./jhat -stack true -refs true -port 8080 -baseline /xxx/dump-baseline.core -debug 1 /Users/xiongyi/Documents/dump-newer.core

 

javap,用于反编译class文件,对于JVM指令集,这里有 完整的文档。

javap -c -v ./Test.class
Classfile xxx/Test.class
  Last modified Nov 11, 2013; size 441 bytes
  MD5 checksum 69488187cc8a8f166bc6dd0d517fb4cb
  Compiled from "Test.java"
public class test.Test
  SourceFile: "Test.java"
  minor version: 0
  major version: 50
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#16         //  java/lang/Object."":()V
   #2 = Integer            1048576
   #3 = Fieldref           #17.#18        //  java/lang/System.out:Ljava/io/PrintStream;
   #4 = Methodref          #19.#20        //  java/io/PrintStream.println:(Ljava/lang/Object;)V
   #5 = Class              #21            //  test/Test
   #6 = Class              #22            //  java/lang/Object
   #7 = Utf8
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               StackMapTable
  #14 = Utf8               SourceFile
  #15 = Utf8               Test.java
  #16 = NameAndType        #7:#8          //  "":()V
  #17 = Class              #23            //  java/lang/System
  #18 = NameAndType        #24:#25        //  out:Ljava/io/PrintStream;
  #19 = Class              #26            //  java/io/PrintStream
  #20 = NameAndType        #27:#28        //  println:(Ljava/lang/Object;)V
  #21 = Utf8               test/Test
  #22 = Utf8               java/lang/Object
  #23 = Utf8               java/lang/System
  #24 = Utf8               out
  #25 = Utf8               Ljava/io/PrintStream;
  #26 = Utf8               java/io/PrintStream
  #27 = Utf8               println
  #28 = Utf8               (Ljava/lang/Object;)V
{
  public test.Test();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."":()V
         4: return
      LineNumberTable:
        line 4: 0

  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: ldc           #2                  // int 1048576
         2: newarray       byte
         4: astore_1
         5: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         8: aload_1
         9: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        12: goto          0
      LineNumberTable:
        line 7: 0
        line 8: 5
        line 9: 12
      StackMapTable: number_of_entries = 1
           frame_type = 0 /* same */

}

文章系本人原创,转载请保持完整性并注明出自 《四火的唠叨》

分享到:
你可能也喜欢:

相关 [jdk 命令行 工具] 推荐:

常用的JDK自带命令行工具

- - 四火的唠叨
文章系本人原创,转载请保持完整性并注明出自 《四火的唠叨》. 在 这里可以找得到这些工具的列表,虽然官网上免责声明为 “The tools described in this section are unsupported and experimental in nature and should be used with that in mind.

JDK自带监控工具

- - ITeye博客
         系统在生产运行过程中最重要的工作莫过于监控与问题的处理,监控是预防问题产生很重要的手段. 在监控过程中可以发现那些模块或进程出现了问题,出现问题后会及时通知问题负责人.         实现监控的手段非常多,有系统级别监控系统,也有监控小工具等等. Java 就已经自带了一些监控工具,可以不借助外部软件的情况下简单、快速查看相应监控信息.

[原]jdk自带检测内存,cpu,线程 的工具——jvisualvm

- - 玩转java
一个很强大的免费工具:JDK6自带的jvisualvm. 其实还有个自带工具 jconsole   这里不多说, 用法跟 jvisualvm 差不多. 这个东西我以前听过说,但一直没有用过. 看到它提供的截图中可以看到各线程的运行状态,所以准备试一下. 在命令行输入jvisualvm. 如果jdk安装正确的话(6.x以上版本),就会看到如下的一个窗口:.

JDK自带工具之问题排查场景示例

- - 后端技术杂谈 | 飒然Hang
获取正在运行的JVM列表. 运行Java飞行记录器(Java Flight Recorder)). 最近看到了大量关于java性能调优、故障排查的文章,自己也写了一篇 Java调优经验谈. 接着此篇文章,其实一直打算写写一些常用调优的工具以及惯常用法的. 后来在 http://java-performance.info这个站点上看到了类似的一篇博文,自我感觉很有指导意义.

[iteye]每个Java开发者都应该知道的5个JDK工具

- - PHP & Java
【编者按】JDK是Java语言的软件开发工具包,没有它就无法编译Java程序. 目前,有许许多多的JDK工具呈现在大家面前,但最常用的莫过于java.exe、javac.exe、jar等. 本文作者Joe拥有多年的Java开发经验,其在博客上分享了一篇文章: 5 JDK Tools Every Java Developer Should Know,笔者对其进行了编译,以下为译文.

Linux命令行文本处理工具

- - CSDN博客系统运维推荐文章
这是看Linuxcast的笔记. Linux命令行文本处理工具. 命令grep用以基于关键字搜索文本. 命令格式grep "关键字",并且通常和管道一起使用,如ls -l | grep "test". -i 在搜索的时候忽略大小写. -Ax 在输出的时候包含结果所在行之后(after)的指定行数. -Bx 在输出的时候包含结果所在行之前(before)的指定行数.

推荐给开发人员的实用命令行工具

- - 博客 - 伯乐在线
英文原文: Ben Dowling ,编译: 伯乐在线——  陈舸. 作为一名Web开发者,当程序出现问题时日子总不是那么好过. 问题可能无处不在,可能是你发送的请求出了错,可能是回复出了错,可能是你使用的某个第三方库出了问题,又或者是一个外部API调用失败了. 优秀的工具对于定位问题出在何处有着无可估量的价值,而且能在一开始就帮助我们阻止问题的出现,总的来说能使我们的工作更有效率.

20个linux命令行工具监视性能(下) - Hackerman

- - 博客园_首页
昨天晚上第一次翻译了《20 Command Line Tools to Monitor Linux Performance》中的前十个命令,翻译得不是很好,今天晚上继续把后面的十个也翻译给大家吧,第一次写博客,写的不是特别的好,希望大家不要介意,也希望大家觉得有什么不对的地方能够多多指教,毕竟小弟还是初学者.

七个用于数据科学(data science)的命令行工具

- - 博客 - 伯乐在线
数据科学是 OSEMN(和 awesome 相同发音),它包括获取(Obtaining)、整理(Scrubbing)、探索(Exploring)、建模(Modeling)和翻译(iNterpreting)数据. 作为一名数据科学家,我用命令行的时间非常长,尤其是要获取、整理和探索数据的时候. 而且我也不是唯一一个这样做的人.

12款最佳Linux命令行终端工具

- - 外刊IT评论网
如果你跟我一样,整天要花大量的时间使用Linux命令行,而且正在寻找一些可替代系统自带的老旧且乏味的终端软件,那你真是找对了文章. 我这里搜集了一些非常有趣的终端软件,可以用来替代debian系的Linux原生终端. 这是一款可配置的雷神之锤风格的终端工具,也就是说,当用户敲击配置好的热键(缺省是F1)时,这个终端会从屏幕的顶端滑出,就跟雷神之锤游戏中的效果一样.