在未捕获的exception上附加jdb

所以,我正在开始一个Java程序,如下所示

java -agentlib:jdwp=transport=dt_socket,address=8000, server=y,suspend=n MyClass 

然后我手动附加调试器,如下所示

 jdb -attach 8000 

我想知道是否有任何方式让我设置jdb,以便在未捕获的exception情况下它自动附加到正在运行的进程(仅)?

原因是我希望避免调试器的开销直到出现未捕获的exception。 但我现在面临的问题是,如果没有附加调试器,那么一旦出现未捕获的exception,JVM就会中止。

编辑:

从Oracle 文档来看,似乎下面的命令可以满足我的需求,但对于Windows机器而言。

 java -agentlib:jdwp=transport=dt_shmem,server=y,onuncaught=y,launch=d:\bin\debugstub.exe MyClass 

谁知道linux等价? 我试过下面的命令。

 java -agentlib:jdwp=transport=dt_socket,address=8000,server=y,onuncaught=y,suspend=n,launch=jdb MyClass 

调试器似乎连接但它立即引发IOError。

 Initializing jdb ... java.io.IOException: Input/output error at java.io.FileInputStream.readBytes(Native Method) at java.io.FileInputStream.read(FileInputStream.java:272) at java.io.BufferedInputStream.read1(BufferedInputStream.java:273) at java.io.BufferedInputStream.read(BufferedInputStream.java:334) at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177) at java.io.InputStreamReader.read(InputStreamReader.java:184) at java.io.BufferedReader.fill(BufferedReader.java:154) at java.io.BufferedReader.readLine(BufferedReader.java:317) at java.io.BufferedReader.readLine(BufferedReader.java:382) at com.sun.tools.example.debug.tty.TTY.(TTY.java:751) at com.sun.tools.example.debug.tty.TTY.main(TTY.java:1067) 

要及时附加调试器确实使用您建议的选项( launchonuncaught )。 但是启动选项在linux上需要更多:

请注意,启动的进程不会在其自己的窗口中启动。 在大多数情况下,启动的进程应该是一个小应用程序,它依次在自己的窗口中启动调试器应用程序。

在您的情况下,由于正在启动它的上下文,jdb无法打开它所需的终端TTY 。根据运行它的环境,您需要构建一个脚本,在新窗口中启动jdb或附加它一个pseduo-tty,以便它可以正常运行。

我通过创建一个使用屏幕来启动终端的脚本来测试它

 #!/bin/bash # according to launch option doc, the first argument is the transport and # the second argument will be the address # screen -dm -L -S autojdb jdb -attach $2 

此脚本将在分离的屏幕中启动jdb ,并为屏幕autojdb命名会话。 您可以使用screen -ls查看屏幕列表。 如果要访问已启动的调试器,请使用screen -r autojdb 。 确保将脚本放在路径中或在启动选项中提供完整路径( /home/me/screenjdb ):

 java -agentlib:jdwp=transport=dt_socket,address=8000,server=y,onuncaught=y,suspend=n,launch=/home/me/screenjdb MyClass 

在我的脚本中,我还将-L传递给了记录会话的屏幕。 这将记录会话,但也可以让您看到由于某种原因附加失败时发生的任何错误。

而不是使用调试器并远程连接一个,为什么不使用Thread.UncaughtExceptionHandler创建一个未捕获的exception处理程序 ?

 public class ThreadCatch { public static void main(String... args) { new ThreadCatch().go(); } public void go() { try { Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("Uncaught exception"); e.printStackTrace(); } }); final Thread thread = new Thread(new A()); thread.start(); thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } class A implements Runnable { int x = 10; @Override public void run() { x++; ObjectTrackingException obj = new ObjectTrackingException(); obj.setThrownFrom(this); throw obj; } } } class ObjectTrackingException extends RuntimeException { private Object thrownFrom; public Object getThrownFrom() { return thrownFrom; } public void setThrownFrom(Object thrownFrom) { this.thrownFrom = thrownFrom; } } 

在此处输入图像描述