7

默认情况下,使用 Hotspot,CTRL-Break 线程转储不会列出哪些线程持有java.lang.concurrent锁。而且我知道使用这些锁,热点无法获得有关在哪个堆栈帧获取锁的信息。如果添加 JVM 选项-XX:+PrintConcurrentLocks,则 CTRL-Break 堆栈转储将列出(在线程的堆栈跟踪之后)该帧持有的所有并发锁。例如:

"D-Java-5-Lock" prio=6 tid=0x00000000069a1800 nid=0x196c runnable [0x000000000770f000]
   java.lang.Thread.State: RUNNABLE
      at com.Tester.longDelay(Tester.java:41)
      at com.Tester$D.run(Tester.java:88)

   Locked ownable synchronizers:
      - <0x00000007d6030898> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

如果没有这个选项,就不可能在事后分析中找出哪个线程持有这个锁。为什么这个选项不是默认的?是否存在一些不明显的性能或稳定性损失?当我搜索找到有关此的讨论时,什么都没有出现。

4

3 回答 3

3

我问过 Oracle(我的雇主有一个支持联系人),答案基本上是该选项可以安全使用,并且默认情况下禁用了许多纯诊断功能,这是其中之一。IMO,如果诊断功能安全稳定并且不会带来性能损失,那么它应该默认启用。这似乎不是(当时)Sun 和(现在)Oracle 的观点。

于 2011-09-01T18:40:19.557 回答
2

好吧,我的猜测是它不稳定,或者 JVM 维护者(Sun-now-Oracle)根本不想将其作为受支持的特性来维护。您可以通过-XX:前缀简单地说明这一点:

使用 -XX 指定的选项不稳定,不建议随意使用。这些选项如有更改,恕不另行通知。

- 来自Java HotSpot VM 选项

同样从该页面,该选项可以通过 JDK 管理界面动态启用或禁用,因此您可以根据需要通过 MXBean 启用它。

标记为可管理的标志可通过 JDK 管理接口 (com.sun.management.HotSpotDiagnosticMXBean API) 以及 JConsole 动态写入。在监控和管理 Java SE 6 平台应用程序中,图 3 显示了一个示例。可管理标志也可以通过 jinfo -flag 设置。

最后,jstack Stack Trace 工具可以随时执行相同的功能,而无需一直启用它。

于 2011-08-16T05:04:13.380 回答
2

因为只有 ReentrantLocks 知道它们与哪些线程相关。要在运行时获取此信息,此方法的实现应遍历堆以查找所有锁及其线程。

于 2017-09-07T22:57:44.513 回答