简体   繁体   English

从Java应用程序将jdb作为进程运行时,输出不完整

[英]Output is incomplete when running jdb as a process from java application

I'm trying to debug a java class from java program. 我正在尝试从Java程序调试Java类。 I created a simple class to test. 我创建了一个简单的类进行测试。 This is my class hello.java and it lies in the folder C:\\Users\\madhawax\\Desktop\\beaufify\\debugging 这是我的类hello.java ,它位于文件夹C:\\Users\\madhawax\\Desktop\\beaufify\\debugging

My problem is that I can't retrieve the part 我的问题是我无法取回零件

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

when I run jdb from java code, but when I manually run jdb from command line I can see it. 从Java代码运行jdb时,但是从命令行手动运行jdb ,可以看到它。

Why do I get only part of the real output? 为什么我只得到真实输出的一部分? How can I fix this? 我怎样才能解决这个问题?

This is my Hello.java class: 这是我的Hello.java类:

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

I used 3 commands to run jdb 我使用了3个命令来运行jdb

jdb
stop in Hello.main
run Hello

Console output when I debug manually using cmd . 使用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]

Output when I run jdb using java code . 使用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)

I used this code to run jdb. 我使用此代码运行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();
}

I suggest you to run your code without try-with-resources : 我建议您在不使用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());
}

In your code try-with-resources will close BufferedWriter after execution: 在您的代码中, 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

Thus, it will close underlying process output stream and this, apparently, leads to closure of jdb process. 因此,它将关闭底层进程的输出流,这显然导致jdb进程的关闭。

You might want to change try-with-resource to try-catch-finally wrapping the whole method. 您可能需要更改try-with-resource,以try-catch-finally方式包装整个方法。

UPDATE : Also, it's a good idea to read output of one command before running next command. 更新 :而且, 运行下一个命令之前先读取一个命令的输出是个好主意。 With your approach: 使用您的方法:

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

There's no pause between command calls. 命令调用之间没有暂停。 jdb might not be able to handle list command at the time (because it's launching VM). jdb当时可能无法处理list命令(因为它正在启动VM)。 As an experiment you can introduce a time gap: 作为实验,您可以引入时间间隔:

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

The superior approach is to read output in between. 更好的方法是在两者之间读取输出。

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

You can use scanner to read the output. 您可以使用扫描仪读取输出。 But, as @vandale pointed out in question comments, Scanner blocks on token and line breaks. 但是,正如@vandale在有问题的注释中指出的那样,扫描程序会阻止令牌和换行符。 You might want to use non-blocking reads to read available output. 您可能要使用非阻塞读取来读取可用输出。 Something like this might work: 这样的事情可能会起作用:

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));
        }
    }
}

This code will also show output that doesn't end with a line break (input prompts, main[1] , etc.) 此代码还将显示不以换行符结尾的输出(输入提示, main[1]等)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 附加到正在运行的 Android 进程时 JDB 不起作用 - JDB doesn't work when attaching to a running Android process Java:从命令行运行时重定向内部进程输出 - Java: Redirecting inner process output when running from command line 尝试使用jdb附加到进程时出现问题 - Problems when trying to attach to a process using jdb 从终端 JDB 调试 libgdx 应用程序 - Debugging a libgdx application from the terminal JDB 从Windows应用程序获取正在运行的Java应用程序的进程ID - get the process id of a running java application from a windows application 可以从jdb中杀死一个java线程吗? - Can a single java thread be killed from jdb? Java中正在运行的应用程序中的后台进程 - background process in a running application in Java 通过命令行jdb运行Java程序可以正确执行,但作为Java命令行执行时会失败 - Running java program through command-line jdb executes correctly but fails when executed as java command-line 从 java 应用程序以其他用户权限运行新进程 - Running new process with other user privileges from java application 在使用“错误”和“输出”流从 java 调用 wget 时,子进程尝试多次运行不完整的命令 - While calling wget from java with consuming the "error" and "output" stream, the sub process tries to run the incomplete command several times
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM