JAVA 根据线程转储中的 ID 查找对象

JAVA Find object based on its id from thread dump

假设我从线程转储中得到了这一行:

waiting to lock <0x0000000301cf21a8> (a foo.bar.MyClass)

如何找到这个对象?我以为调用 System.identityHashCode 并将其转换为十六进制就可以了,但它似乎不匹配。

请注意,threaddump 行中的数字是虚拟内存地址,不是哈希码。

您可以通过使用 Eclipse MAT.

等内存分析器检查 JVM 来完成此操作

我使用了 example from Oracle demonstrating a deadlock situation,使用 jstack 创建了线程转储,使用 Mat 创建了堆转储。

"Thread-1" prio=10 tid=0x00007fb0a00bc000 nid=0x5cc4 waiting for monitor entry [0x00007fb098b25000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at net.noorg.playground.Deadlock$Friend.bowBack(Deadlock.java:19)
    - waiting to lock <0x00000000ebd9f320> (a net.noorg.playground.Deadlock$Friend)
    at net.noorg.playground.Deadlock$Friend.bow(Deadlock.java:16)
    - locked <0x00000000ebd9f368> (a net.noorg.playground.Deadlock$Friend)
    at net.noorg.playground.Deadlock.run(Deadlock.java:34)
    at java.lang.Thread.run(Thread.java:745)

双方都是

- waiting to lock <0x00000000ebd9f320> (a net.noorg.playground.Deadlock$Friend)

- locked <0x00000000ebd9f368> (a net.noorg.playground.Deadlock$Friend)

在 Mat 中创建 heapdump:File > Aquire heapdump > select a process > Finish

打开直方图:

在直方图视图中,您可以使用正则表达式筛选 class 名称。然后您可以显示 class:

的传出对象引用

在引用列表中,您将找到引用 class:

的对象

在该示例中,我们可以看到 name 引用(String 对象)及其各自的值 AlphonseGaston。所以"Alphonse"和"Gaston"就是这个僵局中的关联方

注意,

  • 进行堆转储可能需要几分钟,具体取决于堆大小和系统性能
  • 在转储过程中,JVM 暂停。这可能会导致已建立的网络连接或事务超时。
  • heapdump 将包含敏感信息,如数据库密码、客户密码、私钥、用户数据等。因此您应该小心处理转储(不要通过不安全的连接传输它或未加密地存储它)!

在服务器上,您可以使用 jmap(作为 root 或用户 运行 进程)创建堆转储:

$ jmap -dump:file=heapdump.hprof <PID>

我使用了@guillaumegirod-vitouchkina 的建议 - 我创建了一个小代码,使用 Unsafe 打印内存地址,然后我可以将它与我在线程转储中看到的进行比较。谢谢!