0
点赞
收藏
分享

微信扫一扫

Java调试--排查类工具



jcmd

作用

打印java进程涉及的基本类,线程和VM信息。

jhat

作用

读取内存堆转储,然后可以通过http://ip:7000来查看结果。

示例

假设已经使用jmap工具将堆文件保存为了MyDump.prof

  1. 执行:jhat MyDump.prof
  2. 访问:http://ip:7000

常用操作

Show instance counts for all classes (excluding platform),平台外的所有对象信息

Show heap histogram 以树状图形式展示堆情况

选项

-J<flag>

因为 jhat 命令实际上会启动一个JVM来执行, 通过 -J 可以在启动JVM时传入一些启动参数. 例如, -J-Xmx512m 则指定运行 jhat 的Java虚拟机使用的最大堆内存为 512 MB。如果需要使用多个JVM启动参数,则传入多个 -Jxxxxxx.

-stack false|true

关闭对象分配调用栈跟踪(tracking object allocation call stack)。 如果分配位置信息在堆转储中不可用. 则必须将此标志设置为 false. 默认值为 true.

-refs false|true

关闭对象引用跟踪(tracking of references to objects)。 默认值为 true. 默认情况下, 返回的指针是指向其他特定对象的对象,如反向链接或输入引用(referrers or incoming references), 会统计/计算堆中的所有对象。

-port port-number

设置 jhat HTTP server 的端口号. 默认值 7000.

-exclude exclude-file

指定对象查询时需要排除的数据成员列表文件(a file that lists data members that should be excluded from the reachable objects query)。 例如, 如果文件列列出了 java.lang.String.value , 那么当从某个特定对象 Object o 计算可达的对象列表时, 引用路径涉及 java.lang.String.value 的都会被排除。

-baseline exclude-file

指定一个基准堆转储(baseline heap dump)。 在两个 heap dumps 中有相同 object ID 的对象会被标记为不是新的(marked as not being new). 其他对象被标记为新的(new). 在比较两个不同的堆转储时很有用.

-debug int

设置 debug 级别. 0 表示不输出调试信息。 值越大则表示输出更详细的 debug 信息.

-version

启动后只显示版本信息就退出

-h

显示帮助信息并退出. 同 -help

-help

显示帮助信息并退出. 同 -h

jinfo

作用

查看/调整 虚拟机的参数。

虚拟机参数可通过此命令查看:

Linux环境:java -XX:+PrintFlagsInitial | grep manageable

Window环境:java -XX:+PrintFlagsInitial | findstr manageable

格式

jinfo [option] pid                                                                          (to connect to running process)

jinfo [option] <executable <core>                                               (to connect to a core file)

jinfo [option] [server_id@]<remote server IP or hostname>       (to connect to remote debug server)

示例


命令



作用



jinfo -flags 2788



查看进程号为2788的所有jvm参数



jinfo -sysprops2788



查看进程号为2788的所有java系统参数



jinfo -flag MinHeapFreeRatio 2788



查看进程号为2788的MinHeapFreeRatio 的值



jinfo -flag -PrintGC 27250
jinfo -flag -PrintGCDetails 27250



关闭GC日志功能



jinfo -flag +PrintGC 27250
jinfo -flag +PrintGCDetails 27250



打开GC日志功能


选项


选项



含义



-flag <name>



to print the value of the named VM flag



-flag [+|-]<name>



to enable or disable the named VM flag



-flag <name>=<value>



to set the named VM flag to the given value



-flags



to print VM flags



-sysprops



to print Java system properties



<no option>



to print both of the above



-h | -help



to print this help message


jmap

作用

        打印某个Java进程的内存中的对象、堆信息(以二进制形式)。

        生成的dump文件可通过工具进行分析,从而可以排查出OOM、内存泄露等原因。

可分析jmap生成的dump文件的工具:

  1. MAT(内存分析工具(Memory Analysis Tool))
  2. jprofiler
  3. VisualVM
  4. jhat

其他生成dump的文件的方法

        除了jmap这种方式还有如下方法生成dump文件:

  1. 启动应用时加参数:-XX:HeapDumpOnOutOfMemoryError。
  1. 这样在虚拟机发生OOM的时候自动生成堆的dump文件
  1. kill -3 xxx
  1. kill -3 xxx命令发出进程退出信号"吓唬"一下虚拟机,也能拿到dump文件。

格式

jmap [option] <pid>                               (to connect to running process)

jmap [option] <executable <core>        (to connect to a core file)

jmap [option] [server_id@]<remote server IP or hostname>        (to connect to remote debug server)

示例


命令



作用



jmap -heap <pid>



打印堆信息(Heap Configuration、Eden Space、From Space、To Space、PS Old Generation、internal string)



jmap -dump:live,format=b,file=heap.bin <pid>



把pid的堆信息写到heap.bin里。



jmap -histo <pid>



打印pid的直方图。

可查看当前Java进程创建的活跃对象数目和占用内存大小。


选项


选项



含义



-dump[:live,]format=b,file=<filename>



使用hprof二进制形式,输出jvm的heap内容到文件。 

:live:可选,若指定,则会先触发Full GC,然后再dump数据。



-finalizerinfo



打印正等候回收的对象的信息。



-heap



打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况。



-histo[:live]



打印直方图:每个class的实例数目,内存占用,类全名信息.。VM的内部类名字开头会加上前缀”*”。

:live:可选,若指定,则会先触发Full GC,然后再dump数据。



-F



强制。在pid没有响应的时候,使用-dump或者-histo来强制生成堆信息或者直方图。 在这个模式下,live子参数无效。



-h | -help



打印辅助信息



-J



给jmap启动的jvm传递参数。


jstack

作用

打印java堆栈信息。可以用来定位线程间死锁、锁等待、等待外部资源等。

格式

jstack [-l] <pid>                                                     (to connect to running process)

jstack -F [-m] [-l] <pid>                                         (to connect to a hung process)

jstack [-m] [-l] <executable> <core>                     (to connect to a core file)

jstack [-m] [-l] [server_id@]<remote server IP or hostname>    (to connect to a remote debug server)

注意:64位需指定选项"-J-d64",Windows的jstack只支持这种方式:jstack [-l] pid

示例


命令



作用



jstack pid



打印pid的堆栈信息


选项


选项



含义



-F



“jstack [-l] pid”没有响应的时候强制打印栈信息



-l



长列表。打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表



-m



打印java和native c/c++框架的所有栈信息。



-h | -help



打印帮助信息



pid



java进程id,可以用jps查询


结果含义

线程状态(java.lang.Thread.State)


符号



含义



NEW



未启动的线程的状态



RUNNABLE



表示线程具备所有运行条件:在运行队列中准备操作系统的调度,或者正在运行。



BLOCKED



受阻塞并且正在等待监视器锁的某一线程的线程状态。



WAITING



某一等待线程的线程状态。某一线程因为调用下列方法之一而处于等待状态: 
不带超时值的 Object.wait
不带超时值的 Thread.join



TIMED_WAITING



具有指定等待时间的某一等待线程的线程状态。某一线程因为调用以下带有指定正等待时间的方法之一而处于定时等待状态: 

Thread.sleep
带有超时值的 Object.wait
带有超时值的 Thread.join



TERMINATED



已终止线程的线程状态。线程已经结束执行。


其他结果


结果



含义



waiting on condition



该状态出现在线程等待某个条件的发生,比如等待IO、等待网络、等待sleep时间结束、wait时间结束等,具体等待的原因可以结合stack查看。



waiting for monitor entry



Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class对象的锁。每一个对象都有,也仅有一个 monitor。每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在 “Wait Set”中等待的线程状态是 “in Object.wait()”。


        先看 “Entry Set”里面的线程。我们称被 synchronized保护起来的代码段为临界区。当一个线程申请进入临界区时,它就进入了 “Entry Set”队列。对应的 code就像:

synchronized(obj) {

.........

}

这时有两种可能性:

  1. 该 monitor不被其它线程拥有, Entry Set里面也没有其它等待线程。
  1. 本线程即成为相应类或者对象的 Monitor的 Owner,执行临界区的代码
  1. 该 monitor被其它线程拥有
  1. 本线程在 Entry Set队列中等待。

        在第一种情况下,线程将处于 “Runnable”的状态,而第二种情况下,线程 DUMP会显示处于 “waiting for monitor entry”。


in Object.wait() :当线程获得了 Monitor,进入了临界区之后,如果发现线程继续运行的条件没有满足,它则调用对象(一般就是被 synchronized 的对象)的 wait() 方法,放弃了 Monitor,进入 “Wait Set”队列。只有当别的线程在该对象上调用了 notify() 或者 notifyAll() , “ Wait Set”队列中线程才得到机会去竞争,但是只有一个线程获得对象的 Monitor,恢复到运行态。在 “Wait Set”中的线程, DUMP中表现为: in Object.wait()


jstack分析死锁的例子

public class DeadLockTest {
public static void main(String[] args) {
MyThread myThread = new MyThread();
Thread thread1 = new Thread(myThread, "thread-1");
Thread thread2 = new Thread(myThread, "thread-2");
thread1.start();
thread2.start();
}
private static class MyThread implements Runnable {
private Object object1 = new Object();
private Object object2 = new Object();
public void methodA() {
synchronized (object1) {
synchronized (object2) {
System.out.println("Thread:" + Thread.currentThread().getName() + "invoke methodA");
}
}
}
public void methodB() {
synchronized (object2) {
synchronized (object1) {
System.out.println("Thread:" + Thread.currentThread().getName() + "invoke methodB");
}
}
}
@Override
public void run() {
for(int i = 0; i < 1000; i++) {
methodA();
methodB();
}
}
}
}

        卡住时,jstack -l pid后可直接看到jstack直接输出了死锁信息,从thread1和thread2的线程栈也可以看出出现互相等待。

其他网址

JVM jinfo命令(Java Configuration Info) 用法小结 - NetKillWill

jmap命令_运维_and1kaney的专栏 

jstack命令_Java_and1kaney的专栏

jstack命令(Java Stack Trace)_Java_冯立彬的博客

举报

相关推荐

0 条评论