为什么你会抓住Throwable而只打印堆栈跟踪?

时间:2012-02-29 00:56:30

标签: java exception-handling

我试过在其他线程上寻找答案,但到目前为止我只看到线程表明捕获Throwable是坏事。我的问题是,是否有理由为什么你想要这样做然后在catch块中什么都不做,除了打印出堆栈跟踪?

我最近被带到了一个项目,并负责清理RESTful服务的现有类的错误处理。一些辅助服务类具有try / catch块,它们只捕获Throwable并打印出堆栈跟踪,如下所示:

class MainService {

  SubService1 s1;
  SubService2 s2;

  public doMainService() {
  }

}


class SubService1 {

  public int findSomething() {

    try {
        // Do Something
    } catch (Throwable t) {
        t.printStackTrace();
    }
  }
}

class SubService2 {

  public int findSomethingElse() {

    try {
        // Do Something
    } catch (Throwable t) {
        t.printStackTrace();
    }  
  }

}

是否有可接受的情况?抛出Exception并没有try / catch块的方法会更好吗?

7 个答案:

答案 0 :(得分:4)

出于各种众所周知的原因,这几乎不是一种好的做法。

特别是,它不区分checkedunchecked例外以及errors。更重要的是,此代码的一个影响是允许应用程序在异常处理程序之外执行,这可能由于违反不变量而导致各种奇怪的行为。换句话说,由于捕获的异常可能实际上包括违反的断言,编程错误,线程中断,缺少类,I / O错误,OOM条件甚至库和VM错误,因此除了异常处理程序之外,程序状态实际上是不可预测的。

在极少数情况下,广泛的异常处理可能有意义。想象一下服务器处理多个独立请求。由于在提供其中一个请求时遇到问题,您可能不希望崩溃。由于不依赖于异常处理程序之后的状态,因此您只需打印堆栈跟踪并让某人在服务器继续提供其他请求时进行调查。

即使在这些情况下,也应该仔细考虑是否存在错误,例如应该抓住VirtualMachineError

答案 1 :(得分:2)

我认为人们这样做的一个原因只是因为Java会强制您使用try / catch块包围抛出的调用,或者向方法声明添加抛出。

如果你“知道”你不会发生异常,那么这就是防止它上升的一种方法(因为如果你做了抛出,谁会调用你的代码需要包围一个尝试/捕获等等),但如果确实发生了某些事情,它将转储它而不会崩溃。

答案 2 :(得分:0)

如果您不知道任何其他方式来获取堆栈跟踪并且您想知道如何到达当前位置,则可能会这样做。不是一个很好的理由,但可能是一个原因。这似乎不适合你所看到的;你似乎已经获得了不崩溃的代码,但也没有很好地处理错误。

答案 3 :(得分:0)

我用它来查看我的程序崩溃的确切位置。所以基本上只是为了调试。还要看看它是否以预期的方式流动。

答案 4 :(得分:0)

他们可能希望看到堆栈跟踪而不会导致程序崩溃。

例如,对于线程执行的代码来说,记录异常可能是合适的,但是当线程崩溃是不可接受的,否则什么都不做,因为下一次迭代(比如线程从队列中获取项目)可能会按预期工作。这取决于用例,但对于服务器,您通常希望线程是防弹并记录任何错误,而不是停止任何进一步的处理(但用例可能会有所不同)。

答案 5 :(得分:0)

我们在您的问题中遇到的最简单的示例是关闭输入流.Follwoing是InputStream类中的方法声明。

public void close()抛出IOException

虽然我们调用此方法时可能会抛出异常,但这对程序执行没有任何害处。(因为我们不会再使用那个InputStream)在这种情况下我们应该只记录错误并继续程序。但是,如果您发现一个更改对象状态的异常,那么您必须考虑恢复代码或停止执行。

答案 6 :(得分:0)

永远不要这样做(e.printStackTrace())。许多IDE默认使用它,但它很糟糕(许多应用程序运行时stderr以无法访问的方式重定向,因此,从未见过)。经验法则:

  • 如果你真的不关心异常(永远,永远,永远不会关心),抓住它并做一个大评论,说“我们真的,真的不要”如果抛出这个异常就会关心“
  • 如果从不期望实际抛出异常(接口定义了一个已检查的异常,但您知道impl实际上没有抛出异常),请将异常重新抛出为{{1 (这种方式如果/当底层impl发生变化时,你会发现它很快就会发现它)
  • 如果您认为异常不太可能,并且通常不关心它,请使用适当的日志记录基础结构(log4j,commons logging或java.util.logging)进行日志记录。这样,如果你决定实际关心异常,那么它很可能会在以后你可以看到的地方。