如何嗅探哪个 Java 类(库)正在写入 System.out?

Paw*_*ski 4 java

问题要么很棘手,要么很简单(还不确定):

我目前参与的项目有太多的日志库。我们有 log4j、sl4j、logback,谁知道还有什么......

其中之一是记录一些东西System.out,我已经没有关于如何找出哪个以及何时......

我正在考虑诸如在 sysout 上“设置断点”之类的事情,但我不知道这是否可行。

有任何想法吗?

use*_*ser 5

您可以重定向System.outPrintStream引发错误或将其记录在文件中的自定义。您必须手动通过堆栈跟踪并查找有问题的方法。

创建它:

PrintWriter pw = ...;
PrintStream ps = new PrintStream(System.out) {
  public void write(int b) {
    super.write(b);
    /*try { throw new Error(); } 
    catch (Error e) { e.printStackTrace(pw); }*/

    //Edit: Jeff Wang's answer is a better approach since it doesn't
    // throw an exception and just prints the stacktrace
    new Exception().printStackTrace(pw);

    //You could also write to stderr
    Thread.dumpStack();
  }
};
Run Code Online (Sandbox Code Playgroud)

改变System.out

System.setOut(ps);
Run Code Online (Sandbox Code Playgroud)

如果您在程序开始时设置它,那么每当库打印到System.out、捕获它并写入文件(或其他地方)时,都会抛出错误。如果需要,您可以随时更好地格式化它。

除了测试,这不是一个很好的解决方案,因为它涉及每次写入单个字节时抛出异常(write不过,如果您愿意,可以覆盖其他方法)并且因为您需要手动检查堆栈跟踪。在生产中,你会想要别的东西。

编辑:抛出异常是不必要的。你可以做Thread.dumpStacknew Exception().printStackTrace,正如杰夫王建议的另一个答案


Jef*_*ang 5

我之前在错误上使用过它,以查看实际的根本原因(而不是......等等)

    PrintStream o = new PrintStream(new File("A.txt")) { 
        public void write(byte[] b) 抛出 IOException {
              super.write(b);
              IOException ie = new IOException();
              即.printStackTrace(); //不要扔这个!
        }
    };

并像上面提到的用户一样设置它。这是一种与他使用的方法不同的方法,我不太确定有什么区别,我只记得它有效。