Java 的 JDB(和 Eclipse)在连接到具有许多线程的远程 JVM 时挂起(即通过 TCPIP 传输线程调试信息)

Java's JDB (and Eclipse) hang when connecting to remote JVMs with many threads (i.e. transmitting thread debug information via TCPIP)

问题描述

大家好,

我今天在远程调试新服务器时遇到了问题,最初看起来好像 Eclipse 需要很长时间才能连接到远程 JVM。然而,经过一番调查后,我意识到 jdb 也遇到了类似的问题。一些挖掘发现了这个...

连接到远程 JVM 没有问题。 两个调试器都在几秒钟内正确建立了套接字连接。 jdb 甚至处理命令。但是,在远程调试器成功连接到它之后,Sun Java 1.7.0_60-b19 JVM 在通过 TCPIP 通过网络发送其线程调试信息 (JVMTI/JDWP) 时似乎挂起(或传输速度极慢)。

列出远程 JVM 的线程似乎是问题所在。 JDB 的 threads 命令挂起或执行得非常慢。远程 JVM 上的负载是合理的,并且没有设置任何断点。这个 JVM 上有很多线程并发执行(~2005 个线程),可能会有一些 WAN 延迟,但仍然需要一种方法来成功地使用远程调试器!

观察。我猜这与 JVM 的 Java 调试线协议 (JDWP) 实现通过 TCPIP 低效地传输线程信息有关,因为机器 在地球另一端的 WAN 上。但是 - Windows 到同一台机器的远程桌面连接速度和性能都可以接受。鉴于此,似乎必须等待 45 分钟才能让 Eclipse 或 JDB 列出 JVM 上的线程信息是不可接受的,并且可能是一个错误(或实现得非常糟糕的功能)。

可能与?

有关
  1. http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6401245 - 这个 看起来它是固定的,不应该再是问题了。另外,JVM 运行宁在 Windows 数据中心而不是 Linux。
  2. http://www.eclipsecon.org/2013/comment/reply/1153.html - 可能 解决方案但需要 SAP JVM?
  3. https://github.com/vpotapev/jbreakpoint - 开源jdb接口 但没有解决 Eclipse 的问题。

问题。有没有人有什么想法如何使线程数据传输更高效,以便有效地远程调试JVM?这是 JVM 的 Java 调试有线协议 (JDWP) 中的错误吗?

问题详情

Java 版本:

C:\Users\Administrator>"C:\Program Files\Java\jdk1.7.0_60\bin\java" -version
java version "1.7.0_60"
Java(TM) SE Runtime Environment (build 1.7.0_60-b19)
Java HotSpot(TM) 64-Bit Server VM (build 24.60-b09, mixed mode)

应用程序服务器。 发生在 Weblogic 10g 上。也发生在 IBM WebSphere 8.5

Eclipse。 在尝试使用线程信息填充调试视图时,Eclipse 远程调试无限期挂起。

JDB - Remote. Java 的 jdb 远程调试器在列出带有 thread 的线程时挂起超过 10 分钟命令。然后它列出它们的速度非常慢(每秒 1 个线程,需要 33 分钟才能全部列出)。

"C:\Program Files\Java\jdk1.7.0_60\bin\jdb.exe -connect com.sun.jdi.SocketAttach:hostname=xxx.yyy.com,port=7777
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
Initializing jdb ...
> threads
Group system: <<jdb hangs here trying to get thread information>>

JDB - Local. Java的jdb远程调试器在运行时3秒内执行threads命令在 JVM 的本地机器上。

"C:\Program Files\Java\jdk1.7.0_60\bin\jdb.exe -connect com.sun.jdi.SocketAttach:hostname=xxx.yyy.com,port=7777
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
Initializing jdb ...
> threads
Group system:
> threads
Group system:
  (java.lang.ref.Reference$ReferenceHandler)0x7484                                                                  Reference Handler
  (java.lang.ref.Finalizer$FinalizerThread)0x7485                                                                   Finalizer
  (java.lang.Thread)0x7486                                                                                          ...
GC Daemon
  (java.lang.Thread)0x748b                                                                                          RMI RenewClean-
...
>

经过一些调查和数据包嗅探,似乎远程进程中有大量线程导致调试数据包拥塞以及远程进程调试代理和远程调试器之间的处理延迟反馈循环。基本上,JVM 调试代理不是为高延迟连接或远程调试大量线程而设计的。它也不会尝试压缩 thread/stack/variable 更新信息以缩短到调试器的传输时间。

我们的解决方案最终是在我们的产品中添加线程调试模式,以减少各种服务器线程池的大小,然后跨海外网络的调试突然变得可以接受。

对 Java 社区的未来建议是向 Eclipse 和 Java 调试代理添加线程过滤器功能,以便在之后仅将感兴趣线程的信息传输到调试器每个代码步骤都会发出信号。