常用的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)时,这个终端会从屏幕的顶端滑出,就跟雷神之锤游戏中的效果一样.