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
对象)及其各自的值 Alphonse
和 Gaston
。所以"Alphonse"和"Gaston"就是这个僵局中的关联方
注意,
- 进行堆转储可能需要几分钟,具体取决于堆大小和系统性能
- 在转储过程中,JVM 暂停。这可能会导致已建立的网络连接或事务超时。
- heapdump 将包含敏感信息,如数据库密码、客户密码、私钥、用户数据等。因此您应该小心处理转储(不要通过不安全的连接传输它或未加密地存储它)!
在服务器上,您可以使用 jmap
(作为 root 或用户 运行 进程)创建堆转储:
$ jmap -dump:file=heapdump.hprof <PID>
我使用了@guillaumegirod-vitouchkina 的建议 - 我创建了一个小代码,使用 Unsafe 打印内存地址,然后我可以将它与我在线程转储中看到的进行比较。谢谢!
假设我从线程转储中得到了这一行:
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
对象)及其各自的值 Alphonse
和 Gaston
。所以"Alphonse"和"Gaston"就是这个僵局中的关联方
注意,
- 进行堆转储可能需要几分钟,具体取决于堆大小和系统性能
- 在转储过程中,JVM 暂停。这可能会导致已建立的网络连接或事务超时。
- heapdump 将包含敏感信息,如数据库密码、客户密码、私钥、用户数据等。因此您应该小心处理转储(不要通过不安全的连接传输它或未加密地存储它)!
在服务器上,您可以使用 jmap
(作为 root 或用户 运行 进程)创建堆转储:
$ jmap -dump:file=heapdump.hprof <PID>
我使用了@guillaumegirod-vitouchkina 的建议 - 我创建了一个小代码,使用 Unsafe 打印内存地址,然后我可以将它与我在线程转储中看到的进行比较。谢谢!