隐藏System.out.print类的调用

时间:2011-12-02 22:28:47

标签: java

我正在使用java库(jar文件)。该文件的作者放入了一堆System.out.printSystem.out.println s。有没有办法为特定对象隐藏这些消息?

*编辑:看起来jar文件似乎在创建一堆线程,每个线程都有自己的System.out.println ...

5 个答案:

答案 0 :(得分:41)

使用 Dummy 更改原始的 PrintStream ,并且不使用write()方法。

完成后不要忘记替换原来的 PrintStream

System.out.println("NOW YOU CAN SEE ME");

PrintStream originalStream = System.out;

PrintStream dummyStream = new PrintStream(new OutputStream(){
    public void write(int b) {
        // NO-OP
    }
});

System.setOut(dummyStream);
System.out.println("NOW YOU CAN NOT");

System.setOut(originalStream);
System.out.println("NOW YOU CAN SEE ME AGAIN");

答案 1 :(得分:6)

System.setOut();可能就是你要找的东西

System.setOut(new PrintStream(new OutputStream() {
  public void write(int b) {
    // NO-OP
  }
}));

Source

答案 2 :(得分:4)

除了以前发布的内容之外,我还有两种方法可以做到这一点: 1.使用Java反编译器删除每个System.out调用并重新编译jar。如果你选择这条路线,我会推荐this one 2.您可以使用堆栈跟踪查找调用类型。 (来自How do I find the caller of a method using stacktrace or reflection?

List<String> classNames = ...
final PrintStream originalOut = System.out;
PrintStream filterStream = new PrintStream(new OutputStream() {
    public void write(int b) {
         StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
         if(!classNames.contains(stackTraceElements[someNumber].getClassName()){
              originalOut.write(b);
         }
    }
});
System.setOut(filterStream);

其中classNames是jar文件中每个类的完全限定名称,而someNumber是堆栈中正确的位置,您需要查看(可能是1或2)。

/ E1
经过一些测试后,我认为someNumber所需的数字是10或11.这是因为System.out.print没有直接调用write方法。

用于编写h的示例堆栈跟踪:
(堆栈跟踪在索引中,getClassNamegetFileNamegetMethodName顺序。)

0   java.lang.Thread    null    getStackTrace
1   reflection.StackTrace$1 StackTrace.java write
2   java.io.OutputStream    null    write
3   java.io.PrintStream null    write
4   sun.nio.cs.StreamEncoder    null    writeBytes
5   sun.nio.cs.StreamEncoder    null    implFlushBuffer
6   sun.nio.cs.StreamEncoder    null    flushBuffer
7   java.io.OutputStreamWriter  null    flushBuffer
8   java.io.PrintStream null    write
9   java.io.PrintStream null    print
10  java.io.PrintStream null    println
11  reflection.StackTrace   StackTrace.java main

用于编写\n的示例堆栈跟踪:

0   java.lang.Thread    null    getStackTrace
1   reflection.StackTrace$1 StackTrace.java write
2   java.io.OutputStream    null    write
3   java.io.PrintStream null    write
4   sun.nio.cs.StreamEncoder    null    writeBytes
5   sun.nio.cs.StreamEncoder    null    implFlushBuffer
6   sun.nio.cs.StreamEncoder    null    flushBuffer
7   java.io.OutputStreamWriter  null    flushBuffer
8   java.io.PrintStream null    newLine
9   java.io.PrintStream null    println
10  reflection.StackTrace   StackTrace.java main

reflection.StackTrace是我用来进行测试的主要类。 reflection.StackTrace$1是我的filterStream,我正在System.out.println main方法中调用reflection.StackTrace。{/ p>

/ E2
这11或10的差异似乎是因为println调用printnewLineprint继续调用write,而newLine直接将新行字符写入流。但这并不重要,因为jar不会包含java.io.PrintStream

答案 3 :(得分:0)

如果你有一个更大的程序,请考虑像

public abstract class Output {
    private static final PrintStream out = System.out;
    private static final PrintStream dummy = new PrintStream(new OutputStream() {@Override public void write(int b){} });

    private static boolean globalOutputOn = true;
    public static void toggleOutput() {
        System.setOut((globalOutputOn=!globalOutputOn)?dummy:out);
    }

    public static void toggleOutput(boolean on) {
        globalOutputOn = on;
        System.setOut(on?out:dummy);
    }
}

这保证您可以在不同的类中打开和关闭输出,同时保证能够在以后打开输出。

例如,您可以通过调用

来使用它

toggleOutput(false)在每个方法的开头和

每个方法结束时

toggleOutput(true)

答案 4 :(得分:0)

您的问题的解决方法是方法SysOutController.ignoreSysout();中的here..