1. 程式人生 > >Java異常(exception)效能優化

Java異常(exception)效能優化

在Java中,構造異常物件是”十分”耗時的,其原因是在預設情況下,建立異常物件時會呼叫父類ThrowablefillInStackTrace()方法生成棧追蹤資訊,JDK中的原始碼如下:

public synchronized Throwable fillInStackTrace() {
        if (stackTrace != null ||
            backtrace != null /* Out of protocol state */ ) {
            fillInStackTrace(0); // native方法
            stackTrace = UNASSIGNED_STACK;
        }
        return
this; }

在我自己做的測試中,new一個帶有棧追蹤資訊的Exception物件要比建立不帶追蹤資訊的物件慢50倍以上。雖然列印呼叫棧能夠精確定位到錯誤發生的程式碼所在行,但我們可以考慮一下,真的有必要讓所有異常都生成這些資訊嗎?

我們在開發業務系統的過程中一般都會使用異常機制來實現錯誤處理邏輯,這些異常通常都可以分成兩大類:

  • 業務異常
    這些是我們自定義的、可以預知的異常,丟擲這種異常並不表示系統出了問題,而是正常業務邏輯上的需要,例如使用者名稱密碼錯誤、引數錯誤等。

  • 系統異常
    往往是執行時異常,比如資料庫連線失敗、IO失敗、空指標等,這種異常的產生多數表示系統存在問題,需要人工排查定位。

其實對於業務異常,我們只需要簡單的知道一個描述問題的字串即可,棧追蹤資訊對我們的意義並不大。而對於系統異常,追蹤資訊才是排查錯誤不可或缺的參考。因此我們可以想辦法控制一下,建立業務異常時不生成呼叫棧追蹤資訊以降低開銷,系統異常則正常生成。

其實方法非常簡單,在我們自定義異常時,只需要重寫父類的一個帶有4個引數的構造方法即可,此方法在ExceptionRuntimeException類中都存在:

protected RuntimeException(String message, Throwable cause,
                               boolean
enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); }

這幾個引數的意義如下:

  • message
    異常的描述資訊,也就是在列印棧追蹤資訊時異常類名後面緊跟著的描述字串
  • cause
    導致此異常發生的父異常,即追蹤資訊裡的caused by
  • enableSuppress
    關於異常掛起的引數,這裡我們永遠設為false即可
  • writableStackTrace
    表示是否生成棧追蹤資訊,只要將此引數設為false, 則在構造異常物件時就不會呼叫fillInStackTrace()

例如,業務異常可以這樣定義:

public class XXXException extends RuntimeException {
    /**
     * 僅包含message, 沒有cause, 也不記錄棧異常, 效能最高
     * @param msg
     */
    public XXXException(String msg) {
        this(msg, false);
    }

    /**
     * 包含message, 可指定是否記錄異常
     * @param msg
     * @param recordStackTrace
     */
    public EngineException(String msg, boolean recordStackTrace) {
        super(msg, null, false, recordStackTrace);
    }

    /**
     * 包含message和cause, 會記錄棧異常
     * @param msg
     * @param cause
     */
    public EngineException(String msg, Throwable cause) {
        super(msg, cause, false, true);
    }
}

即通過使用父類中4引數的構造方法精確控制異常類的行為。當我們想要建立”輕量級”異常時,使用第一個構造方法即可;如果我們想將系統級異常封裝成一下,並希望在日誌中列印棧追蹤時,就使用第三個構造方法。

PS: 只有在高併發系統中做上述優化才會有明顯效果。如果拋異常不頻繁的話也不會有明顯效果,因為即便是慢50倍,實際也是納秒級的區別,對一個請求處理來說微不足道。

相關推薦

Java異常(exception)效能優化

在Java中,構造異常物件是”十分”耗時的,其原因是在預設情況下,建立異常物件時會呼叫父類Throwable的fillInStackTrace()方法生成棧追蹤資訊,JDK中的原始碼如下: public synchronized Throwable fil

淺談java異常[Exception]

你在 這也 一點 io操作 www. 新手 公司 manager other 淺談java異常[Exception] 一. 異常的定義 在《java編程思想》中這樣定義 異常:阻止當前方法或作用域繼續執行的問題。雖然java中有異常處理機制,但是要明確一點,決不應該

java流的效能優化1-檔案複製

傳統的I/O速度相對照較慢,它會成為系統性能的瓶頸。所以在java1.4之後提供了NIO,它是一種全新的流:它具有下面特性:        1.為全部的原是型別提供Buffer快取支援; 2.使用java.nio.charset.C

java異常(Exception)處理機制詳解

java異常(Exception)處理機制詳解 目錄 一. 異常的定義  二. 異常掃盲行動  三. 異常的使用 例1. 這個例子主要通過兩個方法對比來演示一下有了異常以後程式碼的執行流程。 例2. 重新丟擲異常 例3. 異常鏈的使用及異常丟失 例

JAVA筆記 —— JVM 效能優化

JVM 引數檢視 java四類八種基本資料型別 第一類:整型 byte short int long 第二類:浮點型 float double 第三類:邏輯型 boolean(它只有兩個值可取true false) 第四類:字元型 char 在棧中可以直接分配記憶體的資料是基本資料型別。 引

JAVA筆記 —— JVM 效能優化

JVM 引數檢視 java四類八種基本資料型別 第一類:整型 byte short int long 第二類:浮點型 float double 第三類:邏輯型 boolean(它只有兩個值可取true

Java 異常(Exception)&自定義異常

一Java異常體系結構 java.lang.Object ----java.lang.Throwable --------java.lang.Exception ------------java.lang.RuntimeException --------java.lang

Java異常 - Exception總結

這篇blog總結的比較詳細了。 如下圖所示,在Java中所有異常的基類均為Throwable類。有兩個子類,分別為Exception和Error。其中Error主要由JVM處理,比如OutOfMemory。 RunTimeException類,指程式執行過程中的異常,同Error共同構成Java中的Unc

java web專案效能優化之五花八門

       最近是做了半年的專案到了最後測試準備上線了,流程走通後開始做一些效能測試,在此期間做了很多效能優化的工作,在此做下筆記,分享一下。交流一下,希望同道中人有新的東西歡迎補充。在此就不做太多的具體操作,主要還是從思路上出發。       效能優化主要從幾個方面著手

Java陣列/集合效能優化

1、 複製陣列元素,使用System類arraycopy()方法替代迴圈賦值在陣列之間複製元素 建議:System類arraycopy()方法複製陣列元素 杜絕:迴圈賦值複製陣列元素 原因

Java 裏的異常(Exception)詳解

告訴 ted 所有 lib string vm虛擬機 例子 nts 判斷 作為一位初學者, 本屌也沒有能力對異常談得很深入. 只不過Java裏關於Exception的東西實在是很多. 所以這篇文章很長就是了.. 一, 什麽是java裏的異常 由於java是c\c

Java 異常Exception e中的egetMessage()和toString()方法的區別

catch area color sys 區別 ssa clas testin tin Exception e中e的getMessage()和toString()方法的區別: 示例代碼1: public class TestInfo { private stati

java異常—檢查異常(checked exception)和未檢查異常(unchecked exception

處理 角度 查找 targe 什麽是 mem 出錯 邏輯 alt 網易面試要我畫異常的結構圖,什麽是檢查異常,什麽是非檢查異常,我當時的表情是這樣的,。我看過,忘了。沒辦法,繼續看,寫博客掌握。 先來看看異常的結構圖,建議你結合JDK一起看。 可以看出異常的家族

javaexception和error有什麽區別,運行時異常和一般異常有什麽區別

顯示 error cat 捕獲 導致 避免 dex 源代碼 tof 1.exception和error都是繼承了throwable類,在java中只有throwable類型的實例才可以被拋出(throw)或者捕獲(catch),它是異常處理機制的基本組成類型 2.excep

菜鳥要做架構師——java效能優化之for迴圈

完成同樣的功能,用不同的程式碼來實現,效能上可能會有比較大的差別,所以對於一些效能敏感的模組來說,對程式碼進行一定的優化還是很有必要的。今天就來說一下java程式碼優化的事情,今天主要聊一下對於for(while等同理)迴圈的優化。 作為三大結構之一的迴圈,在我們編寫程式碼的時候會經常用到。

Java效能優化高階進階

目錄$ b& Z7 N" v3 B├─1 什麼是效能優化2 w5 O/ k6 p- D+ q│  ├─1.1效能優化專題-什麼是效能優化一-.mp4│  ├─1.1效能優化專題-什麼是效能優化二-.mp4│  ├─效能優化.pdf/

JAVA架構師大型分散式高併發電商專案實戰,效能優化,叢集,億級高併發,web安全,快取架構實戰

現任58到家技術委員會主席,高階技術總監,負責企業,支付,營銷、客戶關係等多個後端業務部門。本質,技術人一枚。網際網路架構技術專家,“架構師之路”公眾號作者。曾任百度高階工程師,58同城高階架構師,58同城技術委員會主席,58同城C2C技術部負責人。 內容介紹 1.大資

java異常練習題:定義一個MulException類繼承Exception類,要求兩數相乘等於100報錯,在主類中定義一個方法,在方法中丟擲此異常,在主方法觀察結果

題目描述: 定義一個MulException類繼承Exception類,要求兩數相乘等於100報錯,在主類中定義一個方法,在方法中丟擲此異常,在主方法觀察結果。  定義一個DivException類繼承RuntimeException類,要求兩數相除等於2報錯,在主類中定義

JAVA效能優化,架構師,分散式框架,高可用框架,微服務架構,資料庫優化

程式碼優化,一個很重要的課題。可能有些人覺得沒用,一些細小的地方有什麼好修改的,改與不改對於程式碼的執行效率有什麼影響呢?這個問題我是這麼考慮的,就像大海里面的鯨魚一樣,它吃一條小蝦米有用嗎?沒用,但是,吃的小蝦米一多之後,鯨魚就被餵飽了。 程式碼優化也是一樣,如果專案著眼於儘快無BUG上線,那麼此時可以抓

Java基礎學習總結(135)——Java程式碼效能優化實踐經驗再總結

前言 程式碼優化的最重要的作用應該是:避免未知的錯誤。在程式碼上線執行的過程中,往往會出現很多我們意想不到的錯誤,因為線上環境和開發環境是非常不同的,錯誤定位到最後往往是一個非常小的原因。然而為了解決這個錯誤,我們需要先自驗證、再打包出待替換的class檔案、暫停業務並重啟,對於一個成熟的專