使用自定义异常堆栈跟踪向客户端发送序列化异常

时间:2014-08-27 01:00:55

标签: java

这可能是一个菜鸟问题所以请耐心等待。我试图通过序列化将线路上的异常发送到客户端,但仍保留原因异常堆栈跟踪。客户端可能没有导致异常类。我正在使用setStackTrace方法,但令我感到困惑的是它为什么不起作用。

public class MyException extends Exception {
    private static final long serialVersionUID = 1L;

    public MyException(final String message, final StackTraceElement[] stackTrace) {
         super(message);

        this.setStackTrace(stackTrace);
   }
}

public static void main(String[] args) throws Throwable {
    MyExceptione = new MyException("Failure", new Exception("Original Exception").getStackTrace());
    throw e;
}

这将打印以下内容。缺少根本原因堆栈跟踪。

Exception in thread "main" pkg.MyException: Failure
at pkg.MyException.main(MyException.java:20)

知道我做错了什么吗?

类似的问题:Initialize exception with stacktrace from another exception?它讲述了同样的情况。

1 个答案:

答案 0 :(得分:1)

我用来解决这个问题的一种方法是创建一个特殊的(显然可序列化的)" passthrough"异常(类似于您的MyException)。此异常采用原始异常的堆栈跟踪,消息,和类名。它会覆盖toString()方法以打印原始类名来代替直通例外的类名。重要的一点(正如你所注意到的),是你在创建它之后不能抛出这个异常。相反,使用另一个共享类与直通异常作为"原因"被抛到客户端。注意一个强大的" passthrough异常的实现应该遍历并替换原始异常的整个原因链

基本示例(客户端已知ServerException和PassthroughException):

public class PassthroughException extends RuntimeException {
   private final String _originalName;

   public PassthroughException(Throwable t) {
       super(t.getMessage(), passthrough(t.getCause()));
       _originalName = t.getClass().getName();
       setStackTrace(t.getStackTrace());
   }

   public String toString() {
       String msg = getMessage();
       return _originalName + ((msg != null) ? (": " + msg) : "");
   }

   private static Throwable passthrough(Throwable t) {
     return ((t != null) ? new PassthroughException(t) : null);
   }
}

try {
  // ... do some stuff on server ...
} catch(Throwable t) {
  throw new ServerException(new PassthroughException(t));
}