前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >不可不知的7个JDK命令

不可不知的7个JDK命令

作者头像
bisal
发布2020-05-18 16:12:31
3880
发布2020-05-18 16:12:31
举报
文章被收录于专栏:bisal的个人杂货铺

武培轩(公众号:武培轩)的《不可不知的7个JDK命令》这篇文章,短小精悍,介绍的这7个JDK命令非常实用,值得借鉴。

javap

使用javap可以查看Java字节码反编译的源文件,javap的命令格式如下:

下面来演示下用javap -c对代码进行反编译,首先写个HelloWorld类,如下:

代码语言:javascript
复制
public class HelloWorld {
    public static void main(String []args) {
       System.out.println("Hello World");
    }
}

接着使用javap -c HelloWorld.class就可以反编译得到如下结果:

代码语言:javascript
复制
Compiled from "HelloWorld.java"
public class HelloWorld {
  public HelloWorld();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return


  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String Hello World
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

jps

jps是用来查询当前所有进程pid的,命令的用法如下图所示:

执行jps可以获取本机Java程序的pid,运行结果如下:

代码语言:javascript
复制
[root@wupx ~]# jps
8825 spring-boot-0.0.1-SNAPSHOT.jar

使用jps -mlvV可以获取到这个进程的pid、jar包的名字以及JVM参数等。

代码语言:javascript
复制
[root@wupx ~]# jps -mlvV
8825 /root/spring-boot-0.0.1-SNAPSHOT.jar --server.port=8090 --logging.file=/root/log/spring-boot.log -Xmx1024m -Xms1024m

jstat

jstat主要用于监控JVM,主要是GC信息,在性能优化的时候经常用到,命令内容如下所示:

比如,上面我们通过jps查到的进程号8825,我们使用jstat -gc 8825来查看该进程的GC 信息:

代码语言:javascript
复制
[root@wupx ~]# jstat -gc 8825
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
65536.0 69120.0  0.0   160.0  10425344.0 1036247.8 21135360.0 19489859.7 84608.0 81123.8 9600.0 8834.1  99517 2070.459   0      0.000 2070.459

其中S0C表示当前Survivor0的容量,S1C表示当前Survivor1的容量,S0U表示当前Survivor0的利用率,S1U表示当前Survivor1的利用率,EC表示Eden的容量,EU表示Eden的利用率,OC表示老年代的容量,OU表示老年代的利用率,MC表示Metaspace的容量,MU表示Metaspace的利用率,CCSC表示类指针压缩空间容量,CCSU表示使用的类指针压缩空间,YGC表示新生代GC的次数,YGCT表示新生代GC的时间,FGC表示Full Gc的次数,FGCT表示Full GC的时间,GCT表示GC总时间。

每个对象都有一个指向它自身类的指针,_klass: 指向类的4字节指针,64位平台上_klass: 指向类的8字节的指针,为了节约这些空间,引入了类指针压缩空间。

jcmd

jcmd可以查看JVM信息,常用的命令内容如下:

先使用jcmd 8825 help来查看都支持什么命令:

代码语言:javascript
复制
[root@wupx ~]# jcmd 8825 help
8825:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
VM.classloader_stats
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.finalizer_info
GC.heap_info
GC.run_finalization
GC.run
VM.uptime
VM.dynlibs
VM.flags
VM.system_properties
VM.command_line
VM.version
help

下面我就选一个参数给大家举个例子,比如打印堆的信息,使用jcmd 8825 GC.heap_dump命令:

代码语言:javascript
复制
[root@wupx ~]# jcmd 8825 GC.heap_info
8825:
 PSYoungGen      total 628736K, used 41772K [0x0000000715a00000, 0x0000000746480000, 0x00000007c0000000)
  eden space 609792K, 4% used [0x0000000715a00000,0x00000007173d5478,0x000000073ad80000)
  from space 18944K, 80% used [0x000000073ad80000,0x000000073bc75e68,0x000000073c000000)
  to   space 19968K, 0% used [0x0000000745100000,0x0000000745100000,0x0000000746480000)
 ParOldGen       total 250880K, used 21756K [0x00000005c0e00000, 0x00000005d0300000, 0x0000000715a00000)
  object space 250880K, 8% used [0x00000005c0e00000,0x00000005c233f160,0x00000005d0300000)
 Metaspace       used 44797K, capacity 45562K, committed 45824K, reserved 1089536K
  class space    used 5669K, capacity 5832K, committed 5888K, reserved 1048576K

可以看出可以获取新生代、老年代、元空间、Eden、From Survivor以及To Survivor的大小和占比。

jmap

jmap打印出Java进程内存中Object的情况,或者将JVM中的堆以二进制输出成文本,命令内容如下:

使用jmap -heap 8825查看当前堆的使用信息:

代码语言:javascript
复制
[root@wupx ~]# jmap -heap 8825
Attaching to process ID 8825, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.201-b09


using thread-local object allocation.
Parallel GC with 10 thread(s)


Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 8575254528 (8178.0MB)
   NewSize                  = 178782208 (170.5MB)
   MaxNewSize               = 2858418176 (2726.0MB)
   OldSize                  = 358088704 (341.5MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)


Heap Usage:
PS Young Generation
Eden Space:
   capacity = 624427008 (595.5MB)
   used     = 32083672 (30.597373962402344MB)
   free     = 592343336 (564.9026260375977MB)
   5.138098062536078% used
From Space:
   capacity = 19398656 (18.5MB)
   used     = 15687272 (14.960548400878906MB)
   free     = 3711384 (3.5394515991210938MB)
   80.86782919394004% used
To Space:
   capacity = 20447232 (19.5MB)
   used     = 0 (0.0MB)
   free     = 20447232 (19.5MB)
   0.0% used
PS Old Generation
   capacity = 256901120 (245.0MB)
   used     = 22278496 (21.246429443359375MB)
   free     = 234622624 (223.75357055664062MB)
   8.672012017697703% used


24741 interned Strings occupying 2987512 bytes.

首先会打印堆的一些相关配置,比如最大新生代、元空间的大小等;下面为堆的使用情况,包括新生代的Eden区、S0区、S1区以及老年代。

jmap还可以将堆的信息以文件的形式保存下来,相当于文件快照,执行 jmap -dump:live,format=b,file=heap.bin 8825命令:

代码语言:javascript
复制
[root@wupx ~]# jmap -dump:live,format=b,file=heap.bin 8825
Dumping heap to /root/heap.bin ...
Heap dump file created

这个heap.bin可以使用jhat命令打开,是以html的形式展示的。

jhat

jhat分析Java堆的命令,可以将堆中对象以html的形式显示出来,支持对象查询语言OQL,命令内容如下:

现在执行jhat -port 9999 heap.bin来将刚刚保存的heap.bin以html 展示出来:

代码语言:javascript
复制
[root@wupx ~]# jhat -port 9999 heap.bin
Reading from heap.bin...
Dump file created Tue May 12 22:31:55 CST 2020
Snapshot read, resolving...
Resolving 570997 objects...
Chasing references, expect 114 dots..................................................................................................................
Eliminating duplicate references..................................................................................................................
Snapshot resolved.
Started HTTP server on port 9999
Server is ready.

执行完毕后,打开http://localhost:9999/就可以看到类的实例的堆占用情况,它是按照包名来分组的:

网页的底部还有许多Query方式:

下面以OQL为例,打开后是一个类似SQL查询的窗口,比如输入select s from java.lang.String s where s.value.length >= 100就可以查询字符串长度大于100的实例:

jstack

jstack是堆栈跟踪工具,主要用于打印给定进程pid的堆栈信息,一般在发生死锁或者CPU 100%的时候排查问题使用,可以去查询当前运行的线程以及线程的堆栈信息是什么情况,命令内容如下:

下面执行jstack -F 8825 > jstack.log命令,将线程的信息保存下来:

代码语言:javascript
复制
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.161-b12 mixed mode):


"Attach Listener" #51805777 daemon prio=9 os_prio=0 tid=0x00007f971c001000 nid=0x9cd6 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE


"DestroyJavaVM" #55 prio=5 os_prio=0 tid=0x00007f9fc8009800 nid=0x227a waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE


"http-nio-8111-Acceptor-0" #52 daemon prio=5 os_prio=0 tid=0x00007f96c40c5800 nid=0x2653 runnable [0x00007f97c0df9000]
   java.lang.Thread.State: RUNNABLE
  at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
  at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
  at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
  - locked <0x00007f982c6213c8> (a java.lang.Object)
  at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:455)
  at java.lang.Thread.run(Thread.java:748)


"http-nio-8111-ClientPoller-0" #50 daemon prio=5 os_prio=0 tid=0x00007f9fc8e7e000 nid=0x2651 runnable [0x00007f97c21fb000]
   java.lang.Thread.State: RUNNABLE
  at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
  at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
  at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
  at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
  - locked <0x00007f982c622460> (a sun.nio.ch.Util$3)
  - locked <0x00007f982c622450> (a java.util.Collections$UnmodifiableSet)
  - locked <0x00007f982c622408> (a sun.nio.ch.EPollSelectorImpl)
  at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
  at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:787)
  at java.lang.Thread.run(Thread.java:748)


"Service Thread" #17 daemon prio=9 os_prio=0 tid=0x00007f9fc8379000 nid=0x229d runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE


"C1 CompilerThread10" #15 daemon prio=9 os_prio=0 tid=0x00007f9fc8373800 nid=0x229b waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE


"VM Thread" os_prio=0 tid=0x00007f9fc831c000 nid=0x228d runnable


"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f9fc801e800 nid=0x227b runnable


"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f9fc8020800 nid=0x227c runnable


"VM Periodic Task Thread" os_prio=0 tid=0x00007f9fc837e000 nid=0x229e waiting on condition


JNI global references: 357

因为内容比较多,截取了部分内容,可以看出会打印出线程的信息、状态以及堆栈,也会打印出GC Task的线程信息(ParallelGC属于并行收集器,默认为2个线程),从中可以分析出每个线程都在做什么,如果服务器CPU占用高,可以看有多少个线程处于RUNNABLE状态,一般是由于处于RUNNABLE状态的线程过多,导致CPU过高;如果很多线程处于TIMED_WAITING状态,理论上CPU占用不会很高。

本篇文章主要对JDK常用的内置命令javap、jps、jstat、jcmd、jmap、jhat、jstack进行了简单讲解,大家可以自己在本机进行实践。了解这些命令后会在死锁、CPU占用过高问题的排查、程序性能调优上会有很大的帮助。

参考:

https://docs.oracle.com/javase/8/docs/technotes/tools/index.html#basic

JDK内置命令工具

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/05/14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • javap
  • jps
  • jstat
  • jcmd
  • jmap
  • jhat
  • jstack
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档