Использование ConsoleHandler с собственным PrintStream подавляет System.err

Я хочу, чтобы Java ConsoleHandler использовала System.out вместо err, поэтому я реализовал свой собственный обработчик, который вызывает protected void setOutputStream(OutputStream) родительского класса StreamHandler:

public class ConsoleHandler extends java.util.logging.ConsoleHandler {

    public ConsoleHandler() {

        setOutputStream(System.out); // or System.err
        setLevel(Level.ALL);
    }
}

Я удаляю консольный регистратор по умолчанию и добавляю свой собственный в корневой регистратор:

Logger l = Logger.getLogger("");
for (Handler h : l.getHandlers())
    l.removeHandler(h);
l.addHandler(new ConsoleHandler());

System.out.println("OUT");
System.err.println("ERR");

Проблема: "OUT" всегда печатается, а "ERR" никогда, независимо от потока вывода, который я установил в своем конструкторе ConsoleHandler.


person Andi    schedule 01.08.2018    source источник


Ответы (1)


Трассировка стека (распечатанная в System.err) больше не печатается, без моих изменений печатается как обычно

Это потому, что setOutputStream закрывает ранее назначенный поток System.err. Это известная проблема, описанная в разделе JDK-4827381: вызов ConsoleHandler.setOutputStream(...) закрывает System.err. Что должно было произойти с этим отчетом об ошибке, так это то, что файл StreamHandler.setOutputStream должен вызывать Handler.close вместо flushAndClose().

Вам нужно обернуть существующий поток System.err прокси, который не позволяет закрывать поток. Или просто расширьте StreamHandler и используйте конструктор, который принимает OutputStream.

public class OutConsoleHandler extends StreamHandler {

   public OutConsoleHandler() {
        super(System.out, new SimpleFormatter());
        //TODO: Read level,filter,encoding from LogManager.
   }

    @Override
    public void publish(LogRecord record) {
        super.publish(record);
        super.flush();
    }

    @Override
    public void close() {
        super.flush();
    }
}
person jmehrens    schedule 01.08.2018
comment
Это было мое предположение. Как возможно, что System.err.close() не выдает исключение UnsupportedOperationException? Это не должно быть разрешено в стране Java. Я принимаю ваше решение, указывая на реализацию JDK ConsoleHandler, которая немного сложнее: github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/ - person Andi; 02.08.2018
comment
@Andi Andi Если вы используете logging.properties, вам нужно свернуть свой собственный. Однако, если вы используете код и контролируете, как все запускается, вы использовать существующий обработчик консоли. - person jmehrens; 02.08.2018
comment
Как это возможно? Я думаю, потому что есть мыслимые варианты использования, когда вы действительно хотите, чтобы System.err.close() закрывал поток. - person Stephen C; 02.08.2018