Java異常(exception)性能優(yōu)化

在Java中,構(gòu)造異常對(duì)象是"十分"耗時(shí)的,其原因是在默認(rèn)情況下,創(chuàng)建異常對(duì)象時(shí)會(huì)調(diào)用父類ThrowablefillInStackTrace()方法生成棧追蹤信息杉辙,JDK中的源碼如下:

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

在我自己做的測(cè)試中,new一個(gè)帶有棧追蹤信息的Exception對(duì)象要比創(chuàng)建不帶追蹤信息的對(duì)象慢50倍以上捶朵。雖然打印調(diào)用棧能夠精確定位到錯(cuò)誤發(fā)生的代碼所在行蜘矢,但我們可以考慮一下,真的有必要讓所有異常都生成這些信息嗎综看?

我們?cè)陂_發(fā)業(yè)務(wù)系統(tǒng)的過程中一般都會(huì)使用異常機(jī)制來實(shí)現(xiàn)錯(cuò)誤處理邏輯品腹,這些異常通常都可以分成兩大類:

  • 業(yè)務(wù)異常
    這些是我們自定義的、可以預(yù)知的異常红碑,拋出這種異常并不表示系統(tǒng)出了問題舞吭,而是正常業(yè)務(wù)邏輯上的需要,例如用戶名密碼錯(cuò)誤析珊、參數(shù)錯(cuò)誤等羡鸥。

  • 系統(tǒng)異常
    往往是運(yùn)行時(shí)異常,比如數(shù)據(jù)庫連接失敗忠寻、IO失敗惧浴、空指針等,這種異常的產(chǎn)生多數(shù)表示系統(tǒng)存在問題奕剃,需要人工排查定位衷旅。

其實(shí)對(duì)于業(yè)務(wù)異常哑姚,我們只需要簡(jiǎn)單的知道一個(gè)描述問題的字符串即可,棧追蹤信息對(duì)我們的意義并不大芜茵。而對(duì)于系統(tǒng)異常,追蹤信息才是排查錯(cuò)誤不可或缺的參考倡蝙。因此我們可以想辦法控制一下九串,創(chuàng)建業(yè)務(wù)異常時(shí)不生成調(diào)用棧追蹤信息以降低開銷,系統(tǒng)異常則正常生成寺鸥。

其實(shí)方法非常簡(jiǎn)單猪钮,在我們自定義異常時(shí),只需要重寫父類的一個(gè)帶有4個(gè)參數(shù)的構(gòu)造方法即可胆建,此方法在ExceptionRuntimeException類中都存在:

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

這幾個(gè)參數(shù)的意義如下:

  • message
    異常的描述信息烤低,也就是在打印棧追蹤信息時(shí)異常類名后面緊跟著的描述字符串
  • cause
    導(dǎo)致此異常發(fā)生的父異常,即追蹤信息里的caused by
  • enableSuppress
    關(guān)于異常掛起的參數(shù)笆载,這里我們永遠(yuǎn)設(shè)為false即可
  • writableStackTrace
    表示是否生成棧追蹤信息扑馁,只要將此參數(shù)設(shè)為false, 則在構(gòu)造異常對(duì)象時(shí)就不會(huì)調(diào)用fillInStackTrace()

例如,業(yè)務(wù)異沉棺ぃ可以這樣定義:

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, 會(huì)記錄棧異常
     * @param msg
     * @param cause
     */
    public EngineException(String msg, Throwable cause) {
        super(msg, cause, false, true);
    }
}

即通過使用父類中4參數(shù)的構(gòu)造方法精確控制異常類的行為腻要。當(dāng)我們想要?jiǎng)?chuàng)建"輕量級(jí)"異常時(shí),使用第一個(gè)構(gòu)造方法即可涝登;如果我們想將系統(tǒng)級(jí)異常封裝成一下雄家,并希望在日志中打印棧追蹤時(shí),就使用第三個(gè)構(gòu)造方法胀滚。

PS: 只有在高并發(fā)系統(tǒng)中做上述優(yōu)化才會(huì)有明顯效果趟济。如果拋異常不頻繁的話也不會(huì)有明顯效果,因?yàn)榧幢闶锹?0倍咽笼,實(shí)際也是納秒級(jí)的區(qū)別顷编,對(duì)一個(gè)請(qǐng)求處理來說微不足道。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末褐荷,一起剝皮案震驚了整個(gè)濱河市勾效,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌叛甫,老刑警劉巖层宫,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件规肴,死亡現(xiàn)場(chǎng)離奇詭異彪见,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)讥珍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門抖苦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毁菱,“玉大人米死,你說我怎么就攤上這事≈樱” “怎么了峦筒?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)窗慎。 經(jīng)常有香客問我物喷,道長(zhǎng),這世上最難降的妖魔是什么遮斥? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任峦失,我火速辦了婚禮,結(jié)果婚禮上术吗,老公的妹妹穿的比我還像新娘尉辑。我一直安慰自己,他們只是感情好较屿,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布隧魄。 她就那樣靜靜地躺著,像睡著了一般吝镣。 火紅的嫁衣襯著肌膚如雪堤器。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天末贾,我揣著相機(jī)與錄音闸溃,去河邊找鬼。 笑死拱撵,一個(gè)胖子當(dāng)著我的面吹牛辉川,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拴测,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼乓旗,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了集索?” 一聲冷哼從身側(cè)響起屿愚,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎务荆,沒想到半個(gè)月后妆距,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡函匕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年娱据,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盅惜。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡中剩,死狀恐怖忌穿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情结啼,我是刑警寧澤掠剑,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站郊愧,受9級(jí)特大地震影響澡腾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜糕珊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望毅糟。 院中可真熱鬧红选,春花似錦、人聲如沸姆另。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽迹辐。三九已至蝶防,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間明吩,已是汗流浹背间学。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留印荔,地道東北人低葫。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像仍律,于是被迫代替她去往敵國(guó)和親嘿悬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350