2009-04-12 5 views
2

私はSOに類似の質問があることを認識しますが、私の問題はかなり解決しません。Javaでの特定のスレッドのキャプチャコンソールの出力

Classオブジェクトが与えられた場合、そのClass(存在する場合)のpublic static void mainメソッドを呼び出し、そのmainのコンソール出力を取得するメソッドが必要です方法。呼び出しを行うクラスはデーモンではないスレッドです。

私はすでにコードの一部を持っていますが、コンソールの出力をキャプチャする方法とその上に、この特定のスレッドのみをキャプチャする方法はわかりません。ここで私がこれまで持っているものです。

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の出力をキャプチャする方法についての答えへのリンクです。誰かが与えることができるどんな助けも大いに感謝されるでしょう。

ありがとうございます!

編集:これはテスト用ではなく、最終的にはプロダクションになるものです。

EDIT 2:これはスレッドセーフである必要があります。複数のメインメソッドが他のスレッドによって同時に呼び出される可能性があります。スレッドごとに固有の出力をキャプチャする必要があります。

答えて

2

main()メソッドを使用しているので、同じプロセスにする必要がありますか?そうでなければ、新しいプロセス(java.lang.Process)として作成しようとするかもしれません。

Processクラスは、StdOut,StdErrおよび/またはStdInをキャプチャするために必要なメソッドを提供します。

ノートすべてが独自のプロセスで実行されるため、スレッドセーフで問題はありません。しかし、あなたはまだ場所を見つける必要があります。java here.goes.your.ClassNameでプロセスを実行/作成できるように、.classファイル(または少なくともルート)が入っています。

+0

私はこれを実際に考えていました。これは技術的に可能ですが、クラスファイルは実際にはファイルシステム上にあるためですが、クラスローダーを介してクラスをロードしているので(他の操作を行うために)、それを使うだけでいいです。 –

+0

これは間違いなく良い解決策です。別々のプロセスを使用してください。 – Zarkonnen

+0

ここでは慎重されています(http://stackoverflow.com/questions/342435/java-run-a-callable-in-a-separate-process)。円形の問題のように見えます。新しいファイル(新しいURI(Test.class.getResource( "Test.class")。toString()));多分?このために新しいJavaVMが必要なので、Fileにもう一度移動する必要があります。 –

5

System.setOutを使用し、すべての印刷/書き込みメソッドをオーバーライドする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); 
    } 
} 

次にあなたが

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

でこのストリームを作成して使用することができ、これはかなりではないと私は本当に、しかし別の解決のために懸命に見て、あなたを助言します。

+0

上記の編集2を参照してください。そのような状況ではこれはうまくいかないでしょうか? –

+0

スレッドセーフですが、恐ろしいことです。 – Zarkonnen

-1

System.setOut()とSystem.setErr()を使用できますが、出力は残りのプログラムでもキャプチャされます。

関連する問題