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

标签 java eclipse remote-debugging jvm-hotspot jdb

问题描述

大家好,

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

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

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

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

可能与什么有关?

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

问题。有没有人有任何想法如何使线程数据传输更高效以便JVM可以有效地远程调试?这是 JVM 的 Java 调试有线协议(protocol) (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。尝试使用线程信息填充调试 View 时,Eclipse 远程调试无限期挂起。

JDB - 远程。当使用 thread 命令列出线程时,Java 的 jdb 远程调试器挂起超过 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 - 本地。Java 的jdb 远程调试器在JVM 的本地计算机上运行时,可在3 秒内执行threads 命令。

"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 调试代理不是为高延迟连接或远程调试大量线程而设计的。它也不会尝试压缩线程/堆栈/变量更新信息以缩短到调试器的传输时间。

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

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

关于Java 的 JDB(和 Eclipse)在连接到具有许多线程的远程 JVM 时挂起(即通过 TCPIP 传输线程调试信息),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31278716/

相关文章:

java - 查找包含一个点的矩形

java - 从 Java 按名称加载 C++ 类

java - Scala、SQL Server - 如何使用 Scala 将当前时间戳作为日期时间插入 SQL Server 中?

c++ - 从不兼容的指针类型初始化 - 现在怎么办?

java - android 4.1 中出现空异常,但在 4.2 中工作

c# - VS远程调试问题

java - 获取 JVM 默认加载的 keystore 实例

android - 在 Eclipse 中导入现有的 Android 项目

java - 如何调试远程机器上的 war 文件?

Delphi:现场应用程序错误日志记录