1

我正在尝试从 java 程序调试一个 java 类。我创建了一个简单的类来测试。这是我的课hello.java,它位于文件夹中C:\Users\madhawax\Desktop\beaufify\debugging

我的问题是我无法检索零件

VM Started: Set deferred breakpoint Hello.main
...

当我jdb从 java 代码运行时,但是当我jdb从命令行手动运行时,我可以看到它。

为什么我只得到实际输出的一部分?我怎样才能解决这个问题?

这是我的Hello.java课:

public class Hello {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            System.out.println("loop number "+i);
        }
    }
} 

我使用了 3 个命令来运行 jdb

jdb
stop in Hello.main
run Hello

使用 cmd 手动调试时的控制台输出。

C:\Users\madhawax\Desktop\beaufify\debugging>jdb
Initializing jdb ...
> stop in Hello.main
Deferring breakpoint Hello.main.
It will be set after the class is loaded.
> run Hello
run  Hello
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
>
VM Started: Set deferred breakpoint Hello.main

Breakpoint hit: "thread=main", Hello.main(), line=3 bci=0
3            for (int i = 0; i < 10; i++) {

main[1]

当我使用 java 代码运行 jdb 时的输出。

run:
Initializing jdb ...
> Deferring breakpoint Hello.main.
It will be set after the class is loaded.
> run  Hello
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
> Input stream closed.
BUILD STOPPED (total time: 4 seconds)

我使用此代码运行 jdb。

try {
    ProcessBuilder builder = new ProcessBuilder("C:\\Program Files\\Java\\jdk1.8.0_31\\bin\\jdb.exe");
    builder.directory(new File("C:\\Users\\madhawax\\Desktop\\beaufify\\debugging\\"));
    Process process = builder.start();
    OutputStream stdin = process.getOutputStream();
    InputStream stdout = process.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
    try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin))) {
        writer.write("stop in Hello.main\n");
        writer.flush();
        writer.write("run Hello");
        writer.flush();
    }
    String inputLine;
    Scanner scanner = new Scanner(stdout);
    while (scanner.hasNextLine()) {
        System.out.println(scanner.nextLine());
    }
 } catch (IOException ex) {
    ex.printStackTrace();
}
4

1 回答 1

2

我建议您在没有以下情况下运行代码try-with-resources

Scanner scanner = new Scanner(stdout);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
writer.write("stop in Hello.main\n");
writer.flush();
writer.write("run Hello\n");
writer.flush();

while (scanner.hasNextLine()) {
    System.out.println(scanner.nextLine());
}

在您的代码try-with-resources中将在执行后关闭 BufferedWriter:

try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin)))     {
    writer.write("stop in Hello.main\n");
    writer.flush();
    writer.write("run Hello");
    writer.flush();
} //writer is closed here

因此,它将关闭底层进程输出流,这显然会导致 jdb 进程的关闭。

您可能希望将 try-with-resource 更改为 try-catch-finally 包装整个方法。

更新:另外,在运行下一个命令之前读取一个命令的输出是个好主意。用你的方法:

writer.write("stop in Hello.main\n");
writer.flush();
writer.write("run Hello\n");
writer.flush();
writer.write("list\n");
...

命令调用之间没有停顿。listjdb当时可能无法处理命令(因为它正在启动 VM)。作为一个实验,你可以引入一个时间间隔:

writer.flush();
Thread.sleep(1000);
writer.write("list\n");

更好的方法是在两者之间读取输出。

writer.flush();
readOutput(stdout);
writer.write("list\n");

您可以使用扫描仪读取输出。但是,正如@vandale 在问题评论中指出的那样,Scanner 会阻止令牌和换行符。您可能希望使用非阻塞读取来读取可用输出。像这样的东西可能会起作用:

private void readOutput(InputStream outputStream) throws IOException{
    byte[] buffer = new byte[100000];
    int bytesRead;
    while (outputStream.available() > 0) {
        bytesRead = outputStream.read(buffer);
        if (bytesRead > 0) {
            System.out.print(new String(buffer, 0, bytesRead));
        }
    }
}

此代码还将显示不以换行符结尾的输出(输入提示main[1]等)

于 2015-07-27T04:04:41.527 回答