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

Java 使用自定义异常堆栈跟踪将序列化异常发送到客户端,java,Java,这可能是一个noob问题,所以请容忍我。我试图通过串行化将异常通过线路发送到客户端,但仍然保留原因异常堆栈跟踪。客户端可能没有该原因异常类。我正在使用setStackTrace方法,但它为什么不起作用让我感到困惑 public class MyException extends Exception { private static final long serialVersionUID = 1L; public MyException(final String message,

这可能是一个noob问题,所以请容忍我。我试图通过串行化将异常通过线路发送到客户端,但仍然保留原因异常堆栈跟踪。客户端可能没有该原因异常类。我正在使用
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)
知道我做错了什么吗


类似的问题:它说明了相同的场景。

我用来解决这个问题的一种技术是创建一个特殊的(显然是可序列化的)“passthrough”异常(类似于MyException)。此异常获取原始异常的堆栈跟踪、消息和类名。它重写
toString()
方法以打印原始类名,而不是passthrough异常的类名。重要的一点(正如您所注意到的)是,您不能在创建此异常后抛出它。相反,使用另一个共享类,将passthrough异常作为“原因”抛出到客户端。注意,passthrough异常的“健壮”实现应该遍历并替换原始异常的整个原因链

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


你给客户提供建议的动机是什么?客户是否需要跟踪的详细信息?您正在尝试调试吗?我不一定推荐这样做,但您可以重写
fillInStackTrace()
而不执行任何操作。@robbmj,它主要用于调试目的。
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));
}