如果我运行下面的测试,它失败:

public class CrazyExceptions {
    private Exception exception;

    @Before
    public void setUp(){
        exception = new Exception();
    }

    @Test
    public void stackTraceMentionsTheLocationWhereTheExceptionWasThrown(){
        String thisMethod = new Exception().getStackTrace()[0].getMethodName();
        try {
            throw exception;
        }
        catch(Exception e) {
            assertEquals(thisMethod, e.getStackTrace()[0].getMethodName());
        }
    }
}

通过以下错误:

Expected :stackTraceMentionsTheLocationWhereTheExceptionWasThrown
Actual   :setUp

堆栈跟踪为只是平了躺在。

为什么不是当异常被抛出改写堆栈跟踪?我不是一个Java开发,也许我失去了一些东西。

有帮助吗?

解决方案

当异常被实例化,而不是当它被抛出,创建堆栈跟踪。这是指定的 Java语言规范的行为

20.22.1  public Throwable()

This constructor initializes a newly created Throwable object with null as
its error message string. Also, the method fillInStackTrace (§20.22.5) is
called for this object. 

....

20.22.5  public Throwable fillInStackTrace()

This method records within this Throwable object information about the
current state of the stack frames for the current thread. 

我不知道的为什么的他们做了这样的说法,但如果规范定义了它这样,它至少是一致的所有各种Java虚拟机。

但是,可以通过手动调用exception.fillInStackTrace()刷新。

另外请注意,您应该使用而不是使用Thread.currentThread().getStackTrace()(不良作风)new Exception().getStackTrace()

其他提示

异常的堆栈跟踪是在例外的创建时间填充。否则这将是不可能的捕捉异常,处理它并重新抛出它即可。原来的堆栈跟踪会迷路。

如果要强制这一点,你必须显式调用exception.fillInStackTrace()

由于你没有问那个堆栈跟踪被改写。当你在安装方法创建它,它被设置,你从来没有什么改变它。

Exception类不给你任何机会来设置的方法名称;这是不可改变的。因此,有没有办法,我知道的,你可以重新设置方法名,除非你想求助于像反射的东西令人发指。

如果您正在使用JUnit或TestNG的你@Test注解并没有告诉我,因为我无法看到静态导入,但在这两种情况下,你可以运行一个测试,看是否有特定的异常被抛出使用所述“预期”构件在@Test注解

您不会想要抛出一个异常改变堆栈跟踪,或者你不能安全地重新抛出异常。

public void throwsException() {
    throw new RuntimeException();
}

public void logsException() {
    try {
        throwsException();
    } catch (RuntimeException e) {
        e.printStrackTrace();
        throw e; // doesn't alter the exception.
    }
}

@Test
public void youCanSeeTheCauseOfAnException(){
    try {
        logsException();
    } catch(Exception e) {
        e.printStrackTrace(); // shows you the case of the exception, not where it was last re-thrown.
    }
}

在异常堆栈跟踪对应于“新的”操作中,没有别的。

我觉得假设是,除非你在扔的过程中,你将不会被实例化一个例外,为什么付出代价获得堆栈跟踪两次?

这将是很难重新创建堆栈跟踪,当投掷它,因为这只是发送对象进行。

的异常应该是掷之前完全设置,所以部分的实例的是,以获得堆栈跟踪。

<强>更新

您可以致电 fillInStackTrace() 解决这个问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top