所以,我正在开始一个Java程序,如下所示
java -agentlib:jdwp=transport=dt_socket,address=8000, server=y,suspend=n MyClass
然后我手动附加调试器,如下所示
jdb -attach 8000
我想知道我是否还有设置jdb以便在未捕获的异常情况下自动附加到正在运行的进程?
原因是我希望在出现未捕获的异常之前避免调试器的开销。但是我现在面临的问题是,如果没有附加调试器,那么一旦出现未捕获的异常,JVM就会中止。
编辑:
从Oracle docs看来,下面的命令可以满足我的需要,但对于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.<init>(TTY.java:751)
at com.sun.tools.example.debug.tty.TTY.main(TTY.java:1067)
答案 0 :(得分:3)
要及时附加调试器确实使用了您建议的选项(launch
和onuncaught
)。但launch选项在linux上需要更多:
请注意,启动的进程不会在自己的窗口中启动。在大多数情况下,启动的进程应该是一个小应用程序,它会在自己的窗口中启动调试器应用程序。
在您的情况下,由于正在启动它的上下文,jdb无法打开它所需的终端TTY
。根据运行它的环境,您需要构建一个启动jdb的脚本在新窗口中或将其附加到pseduo-tty以便它可以正常运行。
我通过创建使用screen启动终端
的脚本对此进行了测试#!/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
传递给了记录会话的屏幕。这将记录会话,但也可以让您看到由于某种原因附加失败时发生的任何错误。
答案 1 :(得分:0)
不是使用调试器并远程连接,为什么不使用Thread.UncaughtExceptionHandler
创建uncaught exception handler?
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;
}
}