gpt4 book ai didi

java - 从 java.lang.reflect 方法调用捕获 stdout

转载 作者:行者123 更新时间:2023-12-02 12:02:08 25 4
gpt4 key购买 nike

我有一个应用程序,除其他外,它还通过 java.lang.reflect 运行 Java 方法。正常情况下,其功能正常;然而,一位用户将其与他们的一个 JAR 一起使用,结果出现了一些问题。

正如您在下面的代码中看到的,我尝试从该方法中捕获 stdoutstdin 。但是,当调用该方法时,实际上仅捕获该方法流到 stdout 的第一行内容。

这是相关代码。如果您需要查看更多代码,请告诉我,我将添加更多代码:

String retVal = "";
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();

PrintStream origOut = System.out;
PrintStream origErr = System.err;

System.setOut(new PrintStream(out));
System.setErr(new PrintStream(err));

Exception myException = null;

try {
Object myRetVal = null;
myRetVal = m.invoke(obj, convertedMethodArguments);

if (myRetVal != null)
retVal = myRetVal.toString();
} catch (Exception e) {
myException = e;
}

returnObj.addProperty("stdout", out.toString());
returnObj.addProperty("stderr", err.toString());
returnObj.addProperty("rv", retVal);
returnObj.addProperty("rt", m.getReturnType().toString());

if (myException != null && myException.getCause() != null)
returnObj.addProperty("exception", myException.getCause().toString());
else
returnObj.addProperty("exception", "");

System.setOut(origOut);
System.setErr(origErr);

System.out.print(new Gson().toJson(returnObj));

// TODO: remove, debug purposes only
// Should use normal stdout
try {
System.out.println();
m.invoke(obj, convertedMethodArguments);
} catch (Exception e) {
System.out.println(e.toString());
}

当我执行上面的代码时,它只打印出stdout的第一行。但是,在代码块的底部,我再次调用该方法,但这一次没有任何重定向,并且我从该方法获取了所有 stdout

任何帮助将不胜感激!

编辑#1:好的,明白了。为了好玩,我注释掉了重定向默认系统流的两行(例如 System.setOut 和 System.setErr)。随着这些消失,我现在希望在运行应用程序时将所有 stdout 直接写入控制台。

我在代码的最后添加了一条消息(例如 System.out.println("Testing...");),因此它是最后执行的事情。当我测试应用程序时,我得到第一行 stdout,然后是我的测试消息,然后是 stdout 的其余部分。

我不知道这里发生了什么。

编辑 #2: 根据 @Titus 的建议,我研究了我调用的方法是否正在分离其自己的线程。事实证明,确实如此。创建两个线程:AWT-AppKitAWT-Shutdown。前一个线程似乎处于 RUNNABLE 状态,而后一个线程则处于 TIMED_WAITING 状态。

随着时间的推移,AWT-Shutdown 线程消失,但另一个线程仍保持 Activity 状态,处于 RUNNABLE 状态。一旦我的应用程序退出,我相信我调用的方法也会退出,此时额外的消息将显示在屏幕上(这解释了为什么我无法捕获这段STDOUT)。

我不明白的是为什么这个方法不会在我的应用程序中终止。

最佳答案

调用该方法后尝试刷新流。

这是一个例子:

PrintStream outPR = new PrintStream(out);
System.setOut(outPR);
....
outPR.flush();
returnObj.addProperty("stdout", out.toString());

你甚至可以这样做:

System.setOut(new PrintStream(out, true));
....
System.out.println();
returnObj.addProperty("stdout", out.toString());

当写入\n(新行)时,PrintStream 会自动刷新(如果您使用我使用过的构造函数)。

根据对您问题的编辑,您调用的方法可能正在创建新线程,这意味着该新线程可能会在方法返回后打印到控制台。

如果是这种情况,您必须等到该线程完成才能获取所有输出。

关于java - 从 java.lang.reflect 方法调用捕获 stdout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47171864/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com