Один из наиболее хитрых способов решить эту проблему - предоставить собственную реализацию потока ошибок.Этот поток ошибок затем создает внутреннее исключение и использует его, чтобы увидеть, где печатается исходное исключение.Это, безусловно, злоупотребление исключениями.
«Простая» реализация этого:
System.setErr(new PrintStream(new OutputStream() {
@Override
public void write(byte[] b, int off, int len) throws IOException {
Exception e = new Exception();
StackTraceElement[] elements = e.getStackTrace();
boolean hasSeenPrintStackTrace = false;
for (int i = 0; i < elements.length; i++) {
if (
elements[i].getClassName().equals("java.lang.Throwable") &&
elements[i].getMethodName().equals("printStackTrace")
) {
hasSeenPrintStackTrace = true;
} else {
if (hasSeenPrintStackTrace) {
if (
elements[i].getClassName().equals("me.ferrybig.testpackage.ExceptionTester") &&
elements[i].getMethodName().equals("log1")
) {
return;
}
}
}
}
System.out.write(b, off, len);
}
@Override
public void write(byte[] b) throws IOException {
// TODO copy above implementation to here, exceptions printing only seems to use the above method
System.out.write(b);
}
public void write(int b) {
// TODO copy above implementation to here, exceptions printing only seems to use the above method
System.out.write(b);
}
}));
Приведенный выше код в основном следует всем элементам трассировки стека, пока не найдет класс java.lang.Throwable
,и метод printStackTrace
.С этого момента он устанавливает логический флаг, поэтому он может проверять все фреймов, следующих за ним, и сканировать, если они содержат определенную комбинацию класса и метода.Затем он используется для фильтрации , которая записывает вызов, поэтому он не заканчивается в конечном выводе.
Полный демонстрационный класс: http://tpcg.io/5xnlZ7