当前位置:网站首页 > 编程语言 > 正文

jvisualvm分析dump文件 定位大对象(jvisualvm如何分析dump文件)



jstack全称叫Java Stack Trace,Java的堆栈跟踪工具,用于生成java虚拟机当前时刻的线程快照。

功能主要有两个如下

  • 分析死锁;
  • 分析CPU过高问题。

1.1 命令格式

jstack [ option ] pid 查看当前时间点,指定进程的dump堆栈信息。 jstack [ option ] pid > 文件 将当前时间点的指定进程的dump堆栈信息,写入到指定文件中。# 注:若该文件不存在,则会自动生成; 若该文件存在,则会覆盖源文件。 jstack [ option ] executable core 查看当前时间点,core文件的dump堆栈信息。 jstack [ option ] [server_id@]<remote server IP or hostname> 查看当前时间点,远程机器的dump堆栈信息。

option 参数如下:

名称 说明 -F 当正常输出的请求不被响应时,强制输出线程堆栈。

-m

 打印java和native c/c++ 框架的所有栈信息。可以打印JVM的堆栈,以及Native的栈帧, 一般应用排查不需要使用。 -l 除堆栈外,显示关于锁的附加信息,在发生死锁时可以用jstack -l pid来观察锁持有情况。

1.2 获取CPU飙高的线程id

1.2.1 找到CPU飙高的进程

获取各个进程的CPU和内存情况,并且找到CPU飙高的进程ID,比如进程ID=10843

top
1.2.2 显示java进程的CPU和内存占用情况
top -p 进程id
1.2.3 获取每个线程的CPU和内存占用情况
按H
1.2.4 jstack查看线程情况
# 将10进制线程id转为16进制 printf "%x " 线程id # 查看线程情况 jstack 进程ID | grep -A 10 十六进制的线程ID

其中标注daemon字样的是后台线程。

用户线程中包括:

  1. 线程的一些基本信息:名称、优先级及id
  2. 线程状态:waiting on condition等
  3. 线程的调用栈
  4. 线程锁住的资源:locked<0x3f63d600>

2.1 Monitor(监视器)

在多线程的java程序中,实现线程之间的同步,就要说说Monitor。

Monitor是java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者Class的锁。每一个对象都有,也仅有一个Monitor。

  1. 进入区(Entry Set):表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则进入拥有者;否则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。
  2. 拥有者(The Owner):表示某一线程成功竞争到对象锁。
  3. 等待区(Wait Set):表示线程通过对象的wait方法释放对象的锁,并在等待区等待被唤醒。

一个 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){         ……

2.2 调用修饰

表示线程在方法调用时额外的重要操作。线程dump分析的重要信息。修饰上方的方法调用。

  1. locked<地址>目标:使用synchronized申请对象锁成功,监视器的拥有者;
  2. waiting to lock<地址>目标:使用synchronized申请对象锁未成功,在进入区等待;
  3. waiting on<地址>目标:使用synchronized申请对象锁成功后,调用了wait方法,进入对象的等待区等待。在调用栈顶出线,线程状态为WAITING或TIMED_WAITING;
  4. parking to wait for<地址>目标:park是基本的线程阻塞原语,不通过监视器在对象上阻塞。随concurrent包出现的新的机制,与synchronized体系不同。

2.3 线程状态

  • 死锁,Deadlock(重点关注)
  • 等待资源,Waiting on condition(重点关注)
  • 等待获取管程,Waiting on monitor entry(点关注)
  • 阻塞,Blocked(重点关注)
  • 执行中,Runnable
  • 暂停,Suspended
  • 对象等待中,Object.wait() 或 TIMED_WAITING
  • 停止,Parked

输出信息例如

"Thread-1" prio=10 tid=0x0 nid=0xa waiting on condition [0xef47a000..0xef47ac38] at java.lang.Thread.sleep(Native Method) at testthread.MySleepingThread.method2(MySleepingThread.java:53) - locked <0xef63d600> (a testthread.MySleepingThread) at testthread.MySleepingThread.run(MySleepingThread.java:35) at java.lang.Thread.run(Thread.java:595) </span> 

我们能看到:

  • 线程的状态: waiting on condition
  • 线程的调用栈
  • 线程的当前锁住的资源: <0xef63d600>

Wait on condition

Waiting for monitor entry 和 in Object.wait()
在多线程的 JAVA程序中,实现线程之间的同步,就要说说 Monitor。 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”队列。

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

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

临界区的设置,是为了保证其内部的代码执行的原子性和完整性。但是因为临界区在任何时间只允许线程串行通过,这 和我们多线程的程序的初衷是相反的。 如果在多线程的程序中,大量使用 synchronized,或者不适当的使用了它,会造成大量线程在临界区的入口等待,造成系统的性能大幅下降。如果在线程 DUMP中发现了这个情况,应该审查源码,改进程序。
现在我们再来看现在线程为什么会进入 “Wait Set”。当线程获得了 Monitor,进入了临界区之后,如果发现线程继续运行的条件没有满足,它则调用对象(一般就是被 synchronized 的对象)的 wait() 方法,放弃了 Monitor,进入 “Wait Set”队列。只有当别的线程在该对象上调用了 notify() 或者 notifyAll() , “ Wait Set”队列中线程才得到机会去竞争,但是只有一个线程获得对象的 Monitor,恢复到运行态。在 “Wait Set”中的线程, DUMP中表现为: in Object.wait(),类似于:仔细观察上面的 DUMP信息,你会发现它有以下两行:
- locked <0xef63beb8> (a java.util.ArrayList)
- waiting on <0xef63beb8> (a java.util.ArrayList)
线程的执行中,先用 synchronized 获得了这个对象的 Monitor(对应于 locked <0xef63beb8> )。当执行到 obj.wait(), 线程即放弃了 Monitor的所有权,进入 “wait set”队列(对应于 waiting on <0xef63beb8> )。
往往在你的程序中,会出现多个类似的线程,他们都有相似的 DUMP信息。这也可能是正常的。比如,在程序中,有多个服务线程,设计成从一个队列里面读取请求数据。这个队列就是 lock以及 waiting on的对象。当队列为空的时候,这些线程都会在这个队列上等待,直到队列有了数据,这些线程被 Notify,当然只有一个线程获得了 lock,继续执行,而其它线程继续等待。






2.4 线程动作

线程状态产生的原因:

1、runnable:状态一般为RUNNABLE,表示线程具备所有运行条件,在运行队列中准备操作系统的调度,或者正在运行。
2、in Object.wait():等待区等待,状态为WAITING或TIMED_WAITING。
3、waiting for monitor entry:进入区等待,状态为BLOCKED。
4、waiting on condition:等待去等待,被park。
5、sleeping:休眠的线程,调用了Thread.sleep()。



到此这篇jvisualvm分析dump文件 定位大对象(jvisualvm如何分析dump文件)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 重画什么意思(重笔画是什么意思)2025-07-08 15:18:08
  • 接口402(接口405)2025-07-08 15:18:08
  • 论文一级职称论文硬性要求全解析二级职称论文硬性要求全解析三级职称论文硬性要求全解析是什么意思(论文一级职称论文硬性要求全解析二级职称论文硬性要求全解析三级职称论文硬性要求全解析是什么意思知乎)2025-07-08 15:18:08
  • ip15价格(iphone15官方价目表)2025-07-08 15:18:08
  • 定位打开了无法获取位置安卓手机(安卓手机获取定位失败)2025-07-08 15:18:08
  • max30102心率血氧传感器(max30102心率血氧传感器流程图)2025-07-08 15:18:08
  • 安装虚拟机需要多大硬盘(安装虚拟机需要多大硬盘容量)2025-07-08 15:18:08
  • 哔哩哔哩二维码登录(哔哩哔哩二维码登录在哪)2025-07-08 15:18:08
  • 匿名聊天网页(匿名聊天网页版缘起)2025-07-08 15:18:08
  • qq号需要实名认证码(qq需要实名认证 身份证)2025-07-08 15:18:08
  • 全屏图片