Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
940 views
in Technique[技术] by (71.8m points)

multithreading - Capture Console Output of a Specific Thread in Java

I realize there are similar questions on SO, but they don't quite solve my problem.

I would like a method that, given a Class object, will invoke the "main" method, that is to say, public static void main, on that Class (if it exists) and capture the console output of that main method. The class doing the invocation is a non-daemon thread.

I have part of the code already, but I'm not sure how to capture the console output, and on top of that, how to only capture it for *this specific thread. Here's what I have so far:

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

All I need is some code to, or a link to an answer on how to, capture the System.out and System.err output of the method being invoked. Any help someone can give would be much appreciated.

Thanks in advance!

EDIT: This is NOT for testing only, this will eventually be something put into production.

EDIT 2: This will need to be thread-safe. Multiple main methods will be invoked by other threads possibly at the same time, and I want each thread to only capture its own specific output.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Use System.setOut and then write a subclass of printstream that overrides all print/write methods and logs the data if it comes from a thread you want to monitor.

Pseudocode:

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

Then you can create and use this stream with

HackedPrintStream hps = new HackedPrintStream(System.out);
System.setOut(hps);

I would really advise you to look hard for another solution though, as this is not pretty.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...