簡體   English   中英

為什么你會抓住Throwable而只打印堆棧跟蹤?

[英]Why Would you catch Throwable and do nothing but print a stack trace?

我試過在其他線程上尋找答案,但到目前為止我只看到線程表明捕獲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();
    }  
  }

}

有可能這是可以接受的嗎? 拋出異常並沒有try / catch塊的方法會更好嗎?

出於各種眾所周知的原因,這幾乎不是一種好的做法。

特別是,它不區分已檢查未檢查的異常和錯誤 更重要的是,此代碼的一個影響是允許應用程序在異常處理程序之外執行,這可能由於違反不變量而導致各種奇怪的行為。 換句話說,由於捕獲的異常可能實際上包括違反的斷言,編程錯誤,線程中斷,缺少類,I / O錯誤,OOM條件甚至庫和VM錯誤,因此除了異常處理程序之外,程序狀態實際上是不可預測的。

在極少數情況下,廣泛的異常處理可能有意義。 想象一下服務器處理多個獨立請求。 由於在提供其中一個請求時遇到問題,您可能不希望崩潰。 由於您不依賴於異常處理程序之后的狀態 ,因此您只需打印堆棧跟蹤並讓某人在服務器繼續提供其他請求時進行調查。

即使在這些情況下,也應該仔細考慮是否應該捕獲錯誤,例如VirtualMachineError

我認為人們這樣做的一個原因僅僅是因為Java強迫你使用try / catch塊來包圍調用,或者向方法聲明添加throws。

如果你“知道”你不會發生異常,那么它就是一種防止它上升的方法(因為如果你做了拋出,誰會調用你的代碼需要用try /捕獲等等),但是如果確實發生了某些事情,它會在沒有崩潰的情況下轉儲它。

如果您不知道任何其他方式來獲取堆棧跟蹤並且您想知道如何到達當前位置,則可能會這樣做。 不是一個很好的理由,但可能是一個原因。 這似乎不適合你所看到的; 你似乎已經獲得了不崩潰的代碼,但也沒有很好地處理錯誤。

我用它來查看我的程序崩潰的確切位置。 所以基本上只是為了調試。 也只是為了看它是否以預期的方式流動。

他們可能希望在不崩潰程序的情況下查看堆棧跟蹤。

例如,線程執行的代碼可以適用於記錄異常,但是當線程崩潰是不可接受的,否則什么也不做,因為下一次迭代(比如線程從隊列中獲取項目)可能會按預期工作。 這取決於用例,但對於服務器,您通常希望線程是防彈並記錄任何錯誤,而不是停止任何進一步處理(但用例可能會有所不同)。

我們在您的問題中遇到的最簡單的例子是關閉輸入流.Follwoing是InputStream類中的方法聲明。

public void close()拋出IOException

當我們調用這個方法時,有可能拋出一個異常,這對程序執行沒有害處。(因為我們不會進一步使用那個InputStream)在這種情況下我們應該只記錄錯誤並繼續程序。 但是,如果您發現一個更改對象狀態的異常,那么您必須考慮恢復代碼或停止執行。

永遠不要這樣做( e.printStackTrace() )。 許多IDE默認使用它,但它很糟糕(許多應用程序運行時stderr以無法訪問的方式重定向,因此,從未見過)。 經驗法則:

  • 如果你真的不關心異常(永遠,永遠,永遠不會關心),請抓住它,不要做任何大評論,說“我們真的,真的不關心這個異常是否被拋出”
  • 如果你從未期望實際拋出異常(接口定義了一個已檢查的異常,但你知道impl實際上沒有拋出異常),請重新拋出異常,就像new UnsupportedOperationException("this should never happen", t) (這樣,如果/當底層impl發生變化時,你會發現它很快就會發現它
  • 如果您不希望異常,並且通常不關心它,請使用適當的日志記錄基礎結構(log4j,commons logging或java.util.logging)進行日志記錄。 這樣,如果你決定實際上確實關心異常,那么它很可能會讓你在以后看到某個地方。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM