捕获Java中特定线程的控制台输出
我意识到在这方面也有类似的问题,但它们并不能完全解决我的问题 我想要一个方法,给定一个类对象,它将调用该类(如果存在)上的“main”方法,也就是说,publicstaticvoidmain,并捕获该主方法的控制台输出。执行调用的类是非守护进程线程 我已经有了部分代码,但我不确定如何捕获控制台输出,最重要的是,如何只捕获*这个特定线程的输出。以下是我目前掌握的情况:捕获Java中特定线程的控制台输出,java,multithreading,console,Java,Multithreading,Console,我意识到在这方面也有类似的问题,但它们并不能完全解决我的问题 我想要一个方法,给定一个类对象,它将调用该类(如果存在)上的“main”方法,也就是说,publicstaticvoidmain,并捕获该主方法的控制台输出。执行调用的类是非守护进程线程 我已经有了部分代码,但我不确定如何捕获控制台输出,最重要的是,如何只捕获*这个特定线程的输出。以下是我目前掌握的情况: public class Output extends Thread { private Class testClass;
public class Output extends Thread {
private Class testClass;
public Output(Class clazz) {
this.testClass = clazz;
}
private Method getMainMethod(Class clazz) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (isMainMethod(method)) {
return method;
}
}
return null;
}
private Boolean isMainMethod(Method method) {
return (method.getName().equals("main") &&
Modifier.isStatic(method.getModifiers()) &&
method.getReturnType().equals(Void.class));
}
public void run() {
Method mainMethod = null;
if ((mainMethod = getMainMethod(this.testClass)) == null) {
//if there's no static void main method, throw exception
throw new YouFuckedItUpException();
}
mainMethod.invoke(this.testClass, new String[0]);
return heresWhereImStuckIWantToCaptureTheConsoleOutputAndReturnIt();
}
}
我所需要的只是一些代码,或者一个链接,指向如何捕获所调用方法的System.out和System.err输出的答案。任何人能给予的帮助都将不胜感激
提前谢谢
编辑:这不仅仅用于测试,它最终将投入生产
编辑2:这需要是线程安全的。其他线程可能会同时调用多个主方法,我希望每个线程只捕获自己的特定输出。使用并编写printstream的子类,该子类覆盖所有打印/写入方法,并记录数据(如果数据来自要监视的线程)
伪代码:
public class HackedPrintStream extends PrintStream {
private PrintStream originalStream;
private HashMap<Thread, PrintStream> loggerStreams = new HashMap<Thread, PrintStream>();
public HackedPrintStream(PrintStream originalStream) {
this.originalStream = originalStream;
}
public synchronized void logForThread(Thread threadToLogFor, PrintStream streamToLogTo) {
loggerStreams.put(threadToLogFor, streamToLogTo);
}
/** example overridden print method, you need to override all */
public synchronized void println(String ln) {
PrintStream logPS = loggerStreams.get(Thread.currentThread());
if (logPS != null) { logPS.println(ln); }
originalStream.println(ln);
}
}
不过,我真的建议您努力寻找另一种解决方案,因为这并不漂亮。您可以使用System.setOut()和System.setErr(),但当然,程序的其余部分也会捕获输出。既然您使用了
main()
方法,您需要它处于相同的过程中吗?如果没有,您可以尝试将其创建为一个新进程()
过程
类提供了捕获StdOut
、StdErr
和/或StdIn
的必要方法
注意,由于所有内容都在自己的进程中运行,因此线程安全性应该没有问题。但是,您仍然需要找到.class文件(或至少根文件)所在的位置,以便您可以在此处使用
java.go.your.ClassName
运行/创建进程,请参见上面的编辑2。这在那种情况下是行不通的,是吗?实际上我是这么想的。这在技术上是可能的,因为类文件实际上在文件系统中,但是因为我已经通过类加载器加载了类(在它上执行其他操作),如果我可以使用它,那将是很好的。这肯定是更好的解决方案。使用单独的进程。已在此处讨论()。看起来像一个循环问题。新文件(新URI(Test.class.getResource(“Test.class”).toString());大概对于这个,您需要一个新的JavaVM,因此您必须再次转到该文件。我使用自定义类加载器从文件系统加载.class文件,因此在这种情况下获取它很容易。我认为这将是最好的解决办法。
HackedPrintStream hps = new HackedPrintStream(System.out);
System.setOut(hps);