自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

線上問題復盤,JVM Fast Throw 的故事

云計算 虛擬化
首先,這是一個 悲傷的故事,涉及到JVM 底層優(yōu)化的知識點。想到第一次碰到這種問題時的懵逼,應了句老話:書到用時方恨少!

[[394549]]

首先,這是一個 悲傷的故事,涉及到JVM 底層優(yōu)化的知識點。想到第一次碰到這種問題時的懵逼,應了句老話:書到用時方恨少!

負責的消息中臺在 晚上八點左右,運維群里反饋大量用戶接收不到短信消息。登陸 Kibana 查找對應的 Error 日志,發(fā)現(xiàn)出現(xiàn)了 大量的下標越界異常

當時更...,線上問題得到了修復。但是,出現(xiàn)問題可不得找到問題的產出原因,不然下次有可能還會出現(xiàn)

因為在 ELK 上進行 日志分析不太方便,難以根據(jù)對應異常進行不同緯度上的統(tǒng)計分析,所以聯(lián)系運維同學將故障產生當天的 Info、Error 日志 拉下來進行線下分析

經過日志分析得知,異常的產出有兩種,一種是有堆棧信息,比如:

  1. java.lang.ArrayIndexOutOfBoundsException: -1 
  2. ... 省略堆棧信息 

另外一種,就比較詭異,只有異常,沒有對應的堆棧信息

  1. java.lang.ArrayIndexOutOfBoundsException: null 

第一種問題比較好定位,根據(jù) 異常堆棧信息,定位到了具體代碼,直接進行了修復,難就難在第二種

其實這兩個是一個異常,往后看小伙伴就明白了。后面做的所有事情,都是為了搞清楚兩件事情

  • 為什么異常 message 會輸出 null
  • 為什么堆棧信息沒有輸出打印

JVM Fast Throw

什么是 Fast Throw?

大白話一點來說,就是:當一些異常類型(空指針、下標越界、算術運算等...)在代碼里的固定位置被拋出多次,虛擬機(HotSpot VM)會直接 拋出一個事先分配好、類型匹配的異常對象。此異常對象的 message 和 stack trace 都為空

看到這里相信讀者朋友已經明白了為什么同一種異常,打印出來的日志卻是不一樣內容 了吧。就是因為某一個異常在同一個地方多次被拋出,JVM 拋出一個預分配異常,那么 message、stack trace 相當于被吞掉了

The compiler in the server VM now provides correct stack backtraces for all "cold" built-in exceptions. For performance purposes, when such an exception is thrown a few times, the method may be recompiled. After recompilation, the compiler may choose a faster tactic using preallocated exceptions that do not provide a stack trace. To disable completely the use of preallocated exceptions, use this new flag: -XX:-OmitStackTraceInFastThrow.

JDK 1.5 的發(fā)布文檔介紹中描述了此情況,出現(xiàn)這種優(yōu)化方案的原因是 為了提高性能。當同一種異常在相同的位置被拋出多次,編譯器就會重新編譯此方法。重編譯后,編譯器可能會 使用不提供堆棧跟蹤的預分配異常 來選擇更快的策略

如果想要關閉這種預分配異常的機制,可以使用 -XX:-OmitStackTraceInFastThrow。感興趣的讀者朋友可以看一下發(fā)布說明:https://sourl.cn/PMzVkC

另外通過 JVM 的源碼得知,F(xiàn)ast Throw 機制目前支持五種異常情況,截圖如下

模擬 Fast Throw

上面說的都是理論部分,這個章節(jié)使用代碼來實戰(zhàn)下

  1. List<String> list = new ArrayList(); 
  2. for (int j = 0; j < 10000; j++) { 
  3.     try { 
  4.         list.get(-1); 
  5.     } catch (Exception ex) { 
  6.         int length = ex.getStackTrace().length; 
  7.         System.out.println(String.format("報錯異常 :: %s, 堆棧長度 :: %s", ex, length)); 
  8.     } 

上面程序跑在了 Java8 的環(huán)境中,通過運行程序結果可以看出來,F(xiàn)ast Throw 在 Java 8 中依然生效

如果沒有特別情況,最好不要關閉此特性。因為如果并發(fā)量大的接口,因為程序的 BUG 導致大量的請求在同一代碼處拋出異常,F(xiàn)ast Throw 機制可以節(jié)省很多性能損耗。通過單線程跑測試 Demo 得知,異常調用情況越多,性能差別越大

  開啟  Fast Throw 關閉 Fast Throw
10w 1004ms 3547ms
100 w 6193ms 30928ms
500w 37492ms ...

如果線上環(huán)境觸發(fā)了 Fast Throw 機制,可以通過 向前追溯相同位置、相同異常的日志 來定位問題的產出原因

結言

千言萬語匯成一句話就是,重構有風險,上線需謹慎

針對公共功能的重構,需要包含全量的測試用例,要將問題的產出背景考慮到 極致,亦或者和身邊同事說明需求背景,大家一起想下,可以極大程度避免極端問題的產出

必要的壓力測試 是很重要的,這一點可以很好的將 流量大才能顯現(xiàn)的問題 提前暴露出來

 

故障的產生帶來的意義,有好有壞,壞的點大家都懂得;好的點自然是 積累了線上問題故障排查的經驗,這樣的話,后面公司妹子再遇到相同的問題,大喊一聲:妹子,放開那 BUG,讓我來!

 

責任編輯:武曉燕 來源: 龍臺的技術筆記
相關推薦

2024-10-10 15:32:51

2024-04-25 10:06:03

內存泄漏

2011-12-01 14:06:32

2024-09-30 08:54:10

2023-12-01 08:09:08

2023-10-20 08:04:34

系統(tǒng)重構實踐

2023-02-27 07:40:00

系統(tǒng)重構前端

2020-09-28 06:45:42

故障復盤修復

2021-05-26 10:40:28

Vue3TypeScript前端

2020-02-26 09:00:30

程序員技能開發(fā)者

2019-04-22 09:00:38

2022-03-26 13:31:18

項目node變量

2020-12-15 12:43:53

Nodenode應用NodeJS

2013-02-25 14:31:10

2022-12-05 09:31:21

云數(shù)據(jù)庫FinOps

2024-10-17 08:39:32

2021-01-13 05:50:44

迭代器 javascript設計模式

2012-04-16 13:21:00

2023-09-28 08:00:53

2023-01-05 07:39:28

點贊
收藏

51CTO技術棧公眾號