成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

記一次隱藏很深的 JVM 線上慘案的分析、排查、解決

云計算 虛擬化
本文會給大家講解一個比較特殊的JVM優化案例,這個優化案例本身是因為新手工程師對JVM優化可能了解了一個半吊子,然后不知道從哪里找來了一個非常特殊的JVM參數錯誤的設置了一下,就導致線上系統頻繁的出現Full GC的問題。

 [[276426]]

1、本文背景

本文會給大家講解一個比較特殊的JVM優化案例,這個優化案例本身是因為新手工程師對JVM優化可能了解了一個半吊子,然后不知道從哪里找來了一個非常特殊的JVM參數錯誤的設置了一下,就導致線上系統頻繁的出現Full GC的問題。

但是我們后續大量的優化案例其實都是各種各樣奇形怪狀的場景,因為正是各種奇怪場景才能讓大家逐步積累出來較為豐富的JVM優化實戰經驗

了解的場景越多,自己未來在處理JVM性能問題的時候才能更是得心應手。

2、問題的產生

這個場景的發生大致如下過程:某天團隊里一個新手工程師大概是心血來潮,覺得自己網上看到了某個JVM參數,以為學會了絕世武功秘籍,于是就在當天上線一個系統的時候,自作主張設置了一個JVM參數

這個參數是什么呢?

不用急,跟著看下面的案例分析即可,現在只要知道他設置了一個奇怪的參數,接著事故就發生了。

因為一般中大型公司都是接入類似Zabbix、OpenFalcon或者公司自研的一些監控系統的,監控系統一般都做的很好,可以讓你的系統直接接入進去,然后在上面可以看到每臺機器的CPU、磁盤、內存、網絡的一些負載。

而且可以看到你的JVM的內存使用波動折線圖,還有你的JVM GC發生的頻率折線圖。包括如果你自己上報某個業務指標,也可以在監控系統里看到。

而且一般都會針對線上運行的機器和系統設置一些報警,比如說,你可以設置如果10分鐘內發現一個系統的JVM發生了超過3次Full GC,就必須發送報警給你,可以發送給你的短信、郵箱或者是釘釘之類的IM工具。

類似這樣的監控系統不在我們的專欄范疇內,建議大家自己可以去查閱資料,其實基于我們講解的命令行工具,比如jstat,你可以通過linux上的一些命令,讓jstat自動對jvm進行監控,把監控結果可以輸出到機器的某個文件里去。

然后第二天你就可以去查閱那個文件,也可以看到那臺機器的jvm的一些gc統計。

所以說,沒有可視化工具,用最簡單的命令行工具,其實同樣可以起到類似的效果。

所以那天那個工程師設置了一個JVM參數之后,直接導致線上頻繁接到JVM的Full GC的報警,大家就很奇怪了,于是就開始排查那個系統了。

3、查看GC日志

之前已經給大家講解過如何在啟動系統的時候讓他輸出GC日志,所以一旦發現報警,直接登錄到線上機器,然后就看到對應的GC日志了。

此時我們看到在GC日志中有大量的Full GC的記錄。

那么是為什么導致的Full GC呢?

在日志里,看到了一個“Metadata GC Threshold”的字樣,類似于如下日志:

【Full GC(Metadata GC Threshold)xxxxx, xxxxx】

從這里就知道,這頻繁的Full GC,實際上是JDK 1.8以后的Metadata元數據區導致的,也就是類似我們之前說的永久代。

這個Metadata區域一般是放一些加載到JVM里去的類的。

所以此時就很奇怪了,為什么會因為Metadata區域頻繁的被塞滿,進而觸發Full GC?而且Full GC大家都知道,會帶動CMS回收老年代,還會回收Metadata區域本身。

我們先看看下圖:

記一次隱藏很深的 JVM 線上慘案的分析、排查、解決

4、查看Metaspace內存占用情況

接著我們當然是想看一看Metaspace區域的內存占用情況了,簡單點你可以通過jstat來觀察,如果有監控系統,他會給你展示出來一個Metaspace內存區域占用的波動曲線圖,類似下面這種。

記一次隱藏很深的 JVM 線上慘案的分析、排查、解決

看起來Metaspace區域的內存呈現一個波動的狀態,他總是會先不斷增加,達到一個頂點之后,就會把Metaspace區域給占滿,然后自然就會觸發一次Full GC,Full GC會帶著Metaspace區域的垃圾回收,所以接下來Metaspace區域的內存占用又變得很小了。

5、一個綜合性的分析思路

看到這里,相信大家肯定有一點感覺了,這個很明顯是系統在運行過程中,不停的有新的類產生被加載到Metaspace區域里去,然后不停的把Metaspace區域占滿,接著觸發一次Full GC回收掉Metaspace區域中的部分類。

然后這個過程反復的不斷的循環,進而造成Metaspace區域反復被占滿,然后反復導致Full GC的發生,如下圖所示。

記一次隱藏很深的 JVM 線上慘案的分析、排查、解決

6、到底是什么類不停的被加載?

接著我們就有點奇怪了,到底是什么類不停的被加載到JVM的Metaspace區域里去?

這個時候就需要在JVM啟動參數中加入如下兩個參數了:

  1. “-XX:TraceClassLoading -XX:TraceClassUnloading” 

這兩個參數,顧名思義,就是追蹤類加載和類卸載的情況,他會通過日志打印出來JVM中加載了哪些類,卸載了哪些類。

加入這兩個參數之后,我們就可以看到在Tomcat的catalina.out日志文件中,輸出了一堆日志,里面顯示類似如下的內容:

【Loaded sun.reflect.GeneratedSerializationConstructorAccessor from __JVM_Defined_Class】

明顯可以看到,JVM在運行期間不停的加載了大量的所謂“GeneratedSerializationConstructorAccessor”類到了Metaspace區域里去

如下圖所示

記一次隱藏很深的 JVM 線上慘案的分析、排查、解決

相信就是因為JVM運行期間不停的加載這種奇怪的類,然后不停的把Metaspace區域占滿,才會引發不停的執行Full GC的。

這是一個非常實用的技巧,各位同學一定要掌握,頻繁Full GC不光是老年代觸發的,有時候也會因為Metaspace區域的類太多而觸發。

到此為止,已經慢慢接近真相了。

7、為什么會頻繁加載奇怪的類?

接著遇到類似這種問題,我們就應該找一下Google或者是百度了,當然推薦是用Google。你完全可以看看那種不停加載的類,到底是什么類,是你自己寫的類?還是說JDK內置的類?

比如上面的那個類,如果你查閱一些資料,很容易就會搞明白,那個類大概是在你使用Java中的反射時加載的,所謂反射代碼類似如下所示。

  1. Method method = XXX.class.getDeclaredMethod(xx,xx); 
  2. method.invoke(target,params); 

友情提示一下,反射是Java中最最基礎的一個概念,不懂的朋友自己查一下資料。

簡單來說,就是通過XXX.class獲取到某個類,然后通過geteDeclaredMethod獲取到那個類的方法。

這個方法就是一個Method對象,接著通過Method.invoke可以去調用那個類的某個對象的方法,大概就這個意思。

在執行這種反射代碼時,JVM會在你反射調用一定次數之后就動態生成一些類,就是我們之前看到的那種莫名其妙的類

下次你再執行反射的時候,就是直接調用這些類的方法,這是JVM的一個底層優化的機制。

看到這里,有的小伙伴是不是有點蒙?

其實這倒無所謂,這段話看的蒙絲毫不影響你進行JVM優化的

你只要記住一個結論:如果你在代碼里大量用了類似上面的反射的東西,那么JVM就是會動態的去生成一些類放入Metaspace區域里的。

所以上面看到的那些奇怪的類,就是由于不停的執行反射的代碼才生成的,如下圖所示。

記一次隱藏很深的 JVM 線上慘案的分析、排查、解決

8、JVM創建的奇怪類有什么玄機?

那么接下來我們就很奇怪一件事情,就是JVM為什么要不停的創建那些奇怪的類然后放入Metaspace中去?

其實這就要從一個點入手來分析一下了,因為上面說的那種JVM自己創建的奇怪的類,他們的Class對象都是SoftReference,也就是軟引用的。

大家可千萬別說連類的Class是什么都沒聽說過?簡單來說,每個類其實本身自己也是一個對象,就是一個Class對象,一個Class對象就代表了一個類。同時這個Class對象代表的類,可以派生出來很多實例對象。

舉例來說,Class Student,這就是一個類,他本身是由一個Class類型的對象表示的。

但是如果你走一個Student student = new Student(),這就是實例化了這個Student類的一個對象,這是一個Student類型的實例對象。

所以我們這里所說的Class對象,就是JVM在發射過程中動態生成的類的Class對象,他們都是SoftReference軟引用的。

所謂的軟引用,最早我們再一篇文章里說過,正常情況下不會回收,但是如果內存比較緊張的時候就會回收這些對象。

那么SoftReference對象到底在GC的時候要不要回收是通過什么公式來判斷的呢?

是如下的一個公式:

clock - timestamp <= freespace * SoftRefLRUPolicyMSPerMB。

這個公式的意思就是說,“clock - timestamp”代表了一個軟引用對象他有多久沒被訪問過了,freespace代表JVM中的空閑內存空間,SoftRefLRUPolicyMSPerMB代表每一MB空閑內存空間可以允許SoftReference對象存活多久。

舉個例子,假如說現在JVM創建了一大堆的奇怪的類出來,這些類本身的Class對象都是被SoftReference軟引用的。

然后現在JVM里的空間內存空間有3000MB,SoftRefLRUPolicyMSPerMB的默認值是1000毫秒,那么就意味著,此時那些奇怪的SoftReference軟引用的Class對象,可以存活3000 * 1000 = 3000秒,就是50分鐘左右。

當然上面都是舉例而已,大家都知道,一般來說發生GC時,其實JVM內部或多或少總有一些空間內存的,所以基本上如果不是快要發生OOM內存溢出了,一般軟引用也不會被回收。

所以大家就知道了,按理說JVM應該會隨著反射代碼的執行,動態的創建一些奇怪的類,他們的Class對象都是軟引用的,正常情況下不會被回收,但是也不應該快速增長才對。

9、為什么JVM創建的奇怪的類會不停的變多?

那么究竟為什么JVM創建的那些奇怪的類會不停的變多呢?

原因很簡單,因為文章開頭那個新手工程師不知道從哪里扒出來了SoftRefLRUPolicyMSPerMB這個JVM啟動參數,他直接把這個參數設置為0了。

他想的是,一旦這個參數設置為0,任何軟引用對象就可以盡快釋放掉,不用留存,盡量給內存釋放空間出來,這樣不就可以提高內存利用效率了么?

真是想的很傻很天真。

實際上一旦這個參數設置為0之后,直接導致clock - timestamp <= freespace * SoftRefLRUPolicyMSPerMB這個公式的右半邊是0,就導致所有的軟引用對象,比如JVM生成的那些奇怪的Class對象,剛創建出來就可能被一次Young GC給帶著立馬回收掉一些。

如下圖所示。

 

記一次隱藏很深的 JVM 線上慘案的分析、排查、解決

 

比如JVM好不容易給你弄出來100個奇怪的類,結果因為你瞎設置軟引用的參數,導致突然一次GC就給你回收掉幾十個類

接著JVM在反射代碼執行的過程中,就會繼續創建這種奇怪的類,在JVM的機制之下,會導致這種奇怪類越來越多。

也許下一次gc又會回收掉一些奇怪的類,但是馬上JVM還會繼續生成這種類,最終就會導致Metaspace區域被放滿了,一旦Metaspace區域被占滿了,就會觸發Full GC,然后回收掉很多類,接著再次重復上述循環,如下圖所示。

記一次隱藏很深的 JVM 線上慘案的分析、排查、解決

其實很多人會有一個疑問,到底為什么軟引用的類因為錯誤的參數設置被快速回收之后,就會導致JVM不停創建更多的新的類呢?

其實大家不用去扣這里的細節,這里有大量的底層JDK源碼的實現,異常復雜,要真的說清楚,得好幾篇文章才能講清楚JDK底層源碼的這些細節。

大家只要記住這個結論,明白這個道理就好。

10、如何解決這個問題?

雖然底層JDK的一些實現細節我們沒分析,但是大致梳理出來了一個思路,大家也很清楚問題所在和原因了

解決方案很簡單。在有大量反射代碼的場景下,大家只要把

  1. -XX:SoftRefLRUPolicyMSPerMB=0 

這個參數設置大一些即可,千萬別讓一些新手同學設置為0,可以設置個1000,2000,3000,或者5000毫秒,都可以。

提高這個數值,就是讓反射過程中JVM自動創建的軟引用的一些類的Class對象不要被隨便回收,當時我們優化這個參數之后,就可以看到系統穩定運行了。

基本上Metaspace區域的內存占用是穩定的,不會來回大幅度波動了。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2023-01-04 18:32:31

線上服務代碼

2021-11-23 21:21:07

線上排查服務

2022-12-17 19:49:37

GCJVM故障

2021-11-01 17:29:02

Windows系統Fork

2021-05-31 10:08:44

工具腳本主機

2019-03-15 16:20:45

MySQL死鎖排查命令

2021-05-13 08:51:20

GC問題排查

2024-03-11 08:51:08

JVMSWAP內存

2021-12-12 18:12:13

Hbase線上問題

2017-08-24 17:37:18

DNS緩存分析

2017-09-01 09:17:51

DNS緩存慘案

2023-04-06 07:53:56

Redis連接問題K8s

2020-11-16 07:19:17

線上函數性能

2022-02-08 17:17:27

內存泄漏排查

2024-05-13 08:37:17

炫技H5UI

2017-12-19 14:00:16

數據庫MySQL死鎖排查

2022-11-16 08:00:00

雪花算法原理

2021-03-05 22:41:55

CDH集群CDH集群

2021-03-29 12:35:04

Kubernetes環境TCP

2024-10-10 15:32:51

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品无码永久免费888 | 欧美第一页 | 高清av一区 | 一区二区成人 | 色资源站 | 9999久久| 亚洲精品乱码 | 国产高清精品一区二区三区 | 亚洲精品久久久一区二区三区 | 91资源在线 | 美女天天干天天操 | 日本综合在线观看 | 午夜电影日韩 | 欧美中文字幕在线观看 | 成人h视频 | 黄色国产区| 亚洲a视频 | 欧美在线国产精品 | 久久久123| 亚洲国产成人精品久久久国产成人一区 | 99精品欧美一区二区三区综合在线 | 亚洲视频 欧美视频 | 草在线 | 成人自拍视频网站 | 日批免费看 | 久久精品久久综合 | 91 中文字幕 | 国产中文在线 | 香蕉久久久 | 国产精品高潮呻吟久久av野狼 | 日韩在线观看一区二区三区 | 欧美日韩在线一区二区 | 福利影院在线看 | 亚洲欧美一区二区三区国产精品 | 美女黄视频网站 | 久久久精品视频免费 | 日韩精品免费视频 | 国产精品久久久久久久久久东京 | 少妇一级淫片免费放播放 | 精品久久久久国产 | 日韩欧美在 |