【问题标题】:Detecting write to standard error stream检测写入标准错误流
【发布时间】:2017-06-10 23:04:48
【问题描述】:

有没有办法(不管它有多“hacky”)来检测 Java 的 System.err 何时被写入以便能够在发生这种情况时执行逻辑? — 我目前正在使用Thread 的自定义子类(我们称之为SwallowingThread),它在Thread.run() 的实现中以类似于以下代码的方式吞下了许多异常:

public final class SwallowingThread extends Thread {

    ...

    @Override
    public void run() {
        ServerSocket socket = new ServerSocket(80, 100);
        try {
            Socket connected = socket.accept();
            // Do stuff with socket here
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

然而,在我的代码中,我希望能够处理使用SwallowingThread 实例时发生的UnknownHostExceptionIOException 的情况;有没有办法在它发生后检测到这种捕获并打印到标准错误? — 我最初尝试编写 UncaughtExceptionHandler 来执行此操作,只是发现它没有捕获异常,因为它们被吞下而不是简单地被例如包裹在RuntimeException 中并向前扔。

当然,解决这个问题的一个“更好”的方法是重写类的逻辑,但是没有不接触SwallowingThread的快速和肮脏的解决这个问题的方法吗?

【问题讨论】:

  • 您可以创建一个 PrintStream 包装 System.err 吗? System.setErr(new MyDelegatingPrintStream(System.err));
  • @MuratK,不,我不想简单地将输入 stderr 的数据放到另一个地方:我希望能够执行一些逻辑一次/如果这些数据被写入 stderr。

标签: java multithreading exception exception-handling stderr


【解决方案1】:

正如几个人已经建议的那样,您可以使用自定义 PrintStream

它将替换标准错误流,但也将其封装并在需要时调用它。

由于您感兴趣的是异常和堆栈跟踪,因此覆盖 print(String) 就足够了(println(String) 已经调用此方法 + newLine())。

流可能看起来像这样:

import java.io.PrintStream;

public class CustomPrintStream extends PrintStream {


    public CustomPrintStream(final PrintStream out) {

        super(out);

    }

    @Override
    public void print(final String s) {

        super.print(s);
        // some String is written to the error stream, Do something !

    }

}

你会这样使用它,在你的应用程序开始时,只需调用

System.setErr(new CustomPrintStream(System.err));

【讨论】:

    【解决方案2】:

    你可以实现你自己的类(我称之为 DelegatingErrorPrintStream),它派生自 PrintStream,如果有新的输出,它会通知你,然后委托给 System.err 现在您可以使用将您的 DelegatingErrorPrintStream 设置为 System.err 的输出流 System.setErr(err);

    包括用法的完整示例:

    import java.io.FileNotFoundException;
    import java.io.PrintStream;
    import java.io.UnsupportedEncodingException;
    
    public class ErrorNotifierExample {
    private static final class ErrorDelegatingPrintStream extends PrintStream {
        public ErrorDelegatingPrintStream(PrintStream defaultErr)
                throws FileNotFoundException, UnsupportedEncodingException {
            super(defaultErr);
        }
    
        @Override
        public void print(boolean b) {
            super.print(b);
            notifyListener(b);
        }
    
        @Override
        public void print(char c) {
            super.print(c);
            notifyListener(c);
        }
    
        @Override
        public void print(int i) {
            super.print(i);
            notifyListener(i);
        }
    
        @Override
        public void print(long l) {
            super.print(l);
            notifyListener(l);
        }
    
        @Override
        public void print(float f) {
            super.print(f);
            notifyListener(f);
        }
    
        @Override
        public void print(double d) {
            super.print(d);
            notifyListener(d);
        }
    
        @Override
        public void print(char[] s) {
            super.print(s);
            notifyListener(s);
        }
    
        @Override
        public void print(String s) {
            super.print(s);
            notifyListener(s);
    
        }
    
        @Override
        public void print(Object obj) {
            super.print(obj);
            notifyListener(obj);
    
        }
    
        @Override
        public PrintStream append(CharSequence csq, int start, int end) {
            notifyListener(csq); // TODO will need some special handling
            return super.append(csq, start, end);
        }
    
        private void notifyListener(Object string) {
            // TODO implement your handling here. System.out printing is just an
            // example.
            System.out.println(String.valueOf(string));
        }
    }
    
    public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
        ErrorDelegatingPrintStream errReplacement = new ErrorDelegatingPrintStream(System.err);
        System.setErr(errReplacement);
    
        System.err.println("TEST01");
        throw new RuntimeException("just a test output for ERROR handling");
    }
    }
    

    【讨论】:

    • 所有这些答案都非常好,但这几乎正是我最终要做的事情(特别是通过传递 Consumer<Object> 作为代表代替您的 notifyListener(Object) 逻辑)。
    猜你喜欢
    • 1970-01-01
    • 2012-03-03
    • 2014-08-27
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-27
    相关资源
    最近更新 更多