我正在使用一个Java库(jar文件)。该文件的作者添加了大量的System.out.print
和System.out.println
。是否有办法为特定对象隐藏这些消息?
*编辑:看起来jar文件似乎创建了一堆线程,每个线程都有自己的System.out.println...
我正在使用一个Java库(jar文件)。该文件的作者添加了大量的System.out.print
和System.out.println
。是否有办法为特定对象隐藏这些消息?
*编辑:看起来jar文件似乎创建了一堆线程,每个线程都有自己的System.out.println...
更改原始的PrintStream,用一个Dummy替换它,在其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");
System.setOut();
可能是你要找的。
System.setOut(new PrintStream(new OutputStream() {
public void write(int b) {
// NO-OP
}
}));
System.out.println
和 System.out.print
调用。 - JeffreySystem.out
调用,并重新编译jar文件。如果选择此路线,我建议使用这个。
2. 您可以使用堆栈跟踪来查找调用类型。(来源于如何使用堆栈跟踪或反射查找方法的调用者?)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
的示例堆栈跟踪:
(堆栈跟踪按索引、getClassName
、getFileName
、getMethodName
的顺序排列)。
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
,我在 reflection.StackTrace
的 main
方法中调用了 System.out.println
。println
调用了 print
和 newLine
。 print
继续调用 write
,而 newLine
直接将换行符写入流中。但这并不重要,因为 jar 不会包含 java.io.PrintStream
。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)
来使用它。
System.setOut(dummyStream);
。在调用来自jar的方法之后,请使用System.setOut(originalStream);
。好吗? - Kerem BaydoğandummyStream
**。当你需要在控制台打印内容时,请使用 **originalStream
**。 - Kerem Baydoğan