当 运行 jdb 作为来自 java 应用程序的进程时输出不完整
Output is incomplete when running jdb as a process from java application
我正在尝试从 java 程序中调试 java class。我创建了一个简单的 class 来测试。这是我的 class hello.java
,它位于文件夹 C:\Users\madhawax\Desktop\beaufify\debugging
中
我的问题是我无法取回零件
VM Started: Set deferred breakpoint Hello.main
...
当我从 java 代码 运行 jdb
时,但是当我从命令行手动 运行 jdb
时,我可以看到它。
为什么我只得到真实输出的一部分?我该如何解决这个问题?
这是我的 Hello.java
class:
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]
当我 运行 jdb 使用 java 代码时的输出。
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();
}
我建议你 运行 你的代码没有 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 包装整个方法。
UPDATE:此外,最好在运行下一个命令之前读取一个命令的输出。用你的方法:
writer.write("stop in Hello.main\n");
writer.flush();
writer.write("run Hello\n");
writer.flush();
writer.write("list\n");
...
命令调用之间没有停顿。 jdb 当时可能无法处理 list
命令(因为它正在启动 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]
等)
我正在尝试从 java 程序中调试 java class。我创建了一个简单的 class 来测试。这是我的 class hello.java
,它位于文件夹 C:\Users\madhawax\Desktop\beaufify\debugging
我的问题是我无法取回零件
VM Started: Set deferred breakpoint Hello.main
...
当我从 java 代码 运行 jdb
时,但是当我从命令行手动 运行 jdb
时,我可以看到它。
为什么我只得到真实输出的一部分?我该如何解决这个问题?
这是我的 Hello.java
class:
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]
当我 运行 jdb 使用 java 代码时的输出。
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();
}
我建议你 运行 你的代码没有 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 包装整个方法。
UPDATE:此外,最好在运行下一个命令之前读取一个命令的输出。用你的方法:
writer.write("stop in Hello.main\n");
writer.flush();
writer.write("run Hello\n");
writer.flush();
writer.write("list\n");
...
命令调用之间没有停顿。 jdb 当时可能无法处理 list
命令(因为它正在启动 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]
等)