捕获Java中特定线程的控制台输出

捕获Java中特定线程的控制台输出,java,multithreading,console,Java,Multithreading,Console,我意识到在这方面也有类似的问题,但它们并不能完全解决我的问题 我想要一个方法,给定一个类对象,它将调用该类(如果存在)上的“main”方法,也就是说,publicstaticvoidmain,并捕获该主方法的控制台输出。执行调用的类是非守护进程线程 我已经有了部分代码,但我不确定如何捕获控制台输出,最重要的是,如何只捕获*这个特定线程的输出。以下是我目前掌握的情况: public class Output extends Thread { private Class testClass;

我意识到在这方面也有类似的问题,但它们并不能完全解决我的问题

我想要一个方法,给定一个类对象,它将调用该类(如果存在)上的“main”方法,也就是说,publicstaticvoidmain,并捕获该主方法的控制台输出。执行调用的类是非守护进程线程

我已经有了部分代码,但我不确定如何捕获控制台输出,最重要的是,如何只捕获*这个特定线程的输出。以下是我目前掌握的情况:

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