最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一次詭異的full gc查找問題全過程

 更新時(shí)間:2018年11月07日 10:03:20   作者:半畝方田  
這篇文章主要給大家分享介紹了一次詭異的full gc查找問題全部過程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧啊

背景

一個(gè)服務(wù)突然所有機(jī)器開始頻繁full gc。而服務(wù)本身沒有任何改動(dòng)和發(fā)布記錄。上線查看gc log日志,日志如下:

從日志來看,每次發(fā)生full gc的時(shí)候都比較奇怪,主要有兩點(diǎn),第一、old區(qū)域和perm的區(qū)域使用率很低,沒有到達(dá)觸發(fā)full gc的條件,第二、項(xiàng)目中配置的是CMS,為什么沒有進(jìn)行 CMS GC,直接進(jìn)行了full gc呢。

查找過程

第一、代碼會(huì)不會(huì)是調(diào)用了System.gc()

考慮在使用direct memory的時(shí)候,先判斷direct memory是否足夠,要是不足的話會(huì)使用System.gc()嘗試釋放內(nèi)存。于是直接使用反射去監(jiān)控direct memory。發(fā)現(xiàn)direct memory的使用率始終在10%左右,不可能去調(diào)用System.gc()。

而且此時(shí)去查看jvm參數(shù)已經(jīng)禁止顯示調(diào)用了System.gc()了。

第二、使用 jstat -gccause查看gc原因

想著要是能找到gc的原因就好了。于是使用 jstat -gccause實(shí)時(shí)監(jiān)控gc原因,但是發(fā)現(xiàn)始終是Allocation Failure。但是在監(jiān)控中發(fā)現(xiàn)old區(qū)域中有突然增加800M,通過我司的監(jiān)控平臺(tái)也發(fā)現(xiàn)了old區(qū)域暴漲的現(xiàn)象。監(jiān)控如下:

并且通過jmap -histo pid查看old Gen 突變前后內(nèi)存增加值,發(fā)現(xiàn)增加的800M全部是byte[],并且dump內(nèi)存下來使用MAT查看內(nèi)存,然后并沒有什么收獲。

第三、找到有問題開始時(shí)候的改動(dòng)點(diǎn)

因?yàn)轫?xiàng)目在發(fā)生問題的時(shí)候并沒有改動(dòng)和上線,基本上就排除代碼本身的原因。聯(lián)系運(yùn)維告知那個(gè)時(shí)間點(diǎn),我們所在的服務(wù)節(jié)點(diǎn)上部署了log_agent。

log_agent的作用就是把本地日志上報(bào)到日志中心存儲(chǔ)起來,其架構(gòu)示意圖demo如下:

猜著肯定是和log_agent通信的時(shí)候有bug導(dǎo)致的,于是讓運(yùn)維幫忙把其中一臺(tái)機(jī)器上的log_agent給刪除了,刪除之后full gc恢復(fù)正常。

到此基本上確定了是日志上報(bào)導(dǎo)致的問題。

第四、定位日志上報(bào)的jar具體有問題的代碼

定位到是日志上報(bào)的jar導(dǎo)致的問題之后,就把這個(gè)問題反饋給了相關(guān)負(fù)責(zé)人。但是他們追蹤了很久之后并沒有發(fā)現(xiàn)什么問題。

之后有時(shí)間之后,我就把他們相關(guān)代碼看了一下,發(fā)現(xiàn)其中有段代碼有點(diǎn)問題。有問題代碼如下:

在出入log的的時(shí)候在append中會(huì)調(diào)用sendLogEntry這個(gè)方法,而logEntries本身是個(gè)list對(duì)象,非線程安全的。這樣的話,在多個(gè)線程中同時(shí)輸出日志就有安全問題。于是就在sendLogEntry這個(gè)方法上加上線程安全(synchronized),上線問題解決,沒有發(fā)生頻繁full gc了。

但是多線程下同時(shí)調(diào)用list也不應(yīng)該頻繁full gc啊,這個(gè)地方有bug,但是不應(yīng)該導(dǎo)致頻繁 full gc。我懷疑是client.Log(logEntries); 這個(gè)方法本身不是線程安全的。以為我把線程同步塊鎖在了client.Log(logEntries);這個(gè)代碼塊上。發(fā)現(xiàn)問題也得以解決。

client.Log的代碼就是一個(gè)發(fā)送相關(guān)日志、并接收返回值進(jìn)行確認(rèn),使用的是thrift框架進(jìn)行通信的。于是在接收返回值的地方,給加了點(diǎn)log。代碼如下:

從日志中我們可以看到,從返回值中讀取的字節(jié)流大小最大達(dá)1.2G甚至1.8G,這很明顯不正常啊。因?yàn)閥oung Gen 1.5G,old Gen 1G,必定會(huì)拋OOM。而在最上層捕獲了error,但是默認(rèn)情況下卻沒有l(wèi)og,導(dǎo)致log中看不出任何問題。

回想起我司RPC服務(wù)也是用的thrift是用的連接池的方式,所以client肯定是非線程安全的。

問題定位到之后,準(zhǔn)備反饋給那個(gè)人。發(fā)現(xiàn)那個(gè)人已經(jīng)離職了。于是嘗試升級(jí)到最新的jar之后,發(fā)現(xiàn)他們?cè)趕endLogEntry這個(gè)方法上加上了synchronized。

總結(jié)

上面給出了總結(jié)后應(yīng)該遵循的定位問題步驟。真實(shí)的查找過程絕不是按照上面的那個(gè)過程來的,這個(gè)問題的追查持續(xù)了大概兩周(每天投入1-2個(gè)小時(shí)左右吧?)。

主要有兩個(gè)坑:

gc log。開始的時(shí)候關(guān)注點(diǎn)一直在gc log上。從gc log來看根本不滿足發(fā)生full gc的條件。于是專注點(diǎn)在認(rèn)為引入的jar有在調(diào)System.gc()并沒有注意到這個(gè)-XX:+DisableExplicitGC參數(shù)

對(duì)Error的處理。我司日志中心提供的jar居然直接忽略了Error導(dǎo)致了OOM日志一直沒有顯示出來,不然問題發(fā)生時(shí)肯定就能直接定位到了。

JVM拋出OOM之后,就算配置的是CMS,JVM仍舊是使用的Full GC來回收內(nèi)存。因?yàn)镃MS會(huì)有內(nèi)存碎片化問題,已經(jīng)發(fā)生了OOM,可能是因?yàn)闆]有連續(xù)內(nèi)存存放新申請(qǐng)的對(duì)象,F(xiàn)ull GC沒有內(nèi)存碎片的問題,所以直接使用Full GC回收的策略是合理的。

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • Java序列化機(jī)制詳解

    Java序列化機(jī)制詳解

    Java 序列化機(jī)制是一種將對(duì)象轉(zhuǎn)換為字節(jié)流的過程,以便在網(wǎng)絡(luò)上傳輸或保存到文件中,并能在需要時(shí)將字節(jié)流還原為對(duì)象,這一機(jī)制通過實(shí)現(xiàn) java.io.Serializable 接口來實(shí)現(xiàn),同時(shí)涉及到一些關(guān)鍵概念和注意事項(xiàng),需要的朋友可以參考下
    2023-12-12
  • Redis緩存及熱點(diǎn)key問題解決方案

    Redis緩存及熱點(diǎn)key問題解決方案

    這篇文章主要介紹了Redis緩存及熱點(diǎn)key問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Java泛型在集合使用與自定義及繼承上的體現(xiàn)和通配符的使用

    Java泛型在集合使用與自定義及繼承上的體現(xiàn)和通配符的使用

    泛型又稱參數(shù)化類型,是Jdk5.0 出現(xiàn)的新特性,解決數(shù)據(jù)類型的安全性問題,在類聲明或?qū)嵗瘯r(shí)只要指定好需要的具體的類型即可。Java泛型可以保證如果程序在編譯時(shí)沒有發(fā)出警告,運(yùn)行時(shí)就不會(huì)產(chǎn)生ClassCastException異常。同時(shí),代碼更加簡(jiǎn)潔、健壯
    2021-09-09
  • springboot+mybatis-plus實(shí)現(xiàn)自動(dòng)建表的示例

    springboot+mybatis-plus實(shí)現(xiàn)自動(dòng)建表的示例

    本文主要介紹了springboot+mybatis-plus實(shí)現(xiàn)自動(dòng)建表的示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • Java 8中字符串拼接新姿勢(shì)StringJoiner詳解

    Java 8中字符串拼接新姿勢(shì)StringJoiner詳解

    在本篇文章里小編給大家整理了關(guān)于Java 8中字符串拼接新姿勢(shì)StringJoiner的詳解內(nèi)容,需要的朋友們參考下。
    2019-09-09
  • MyBatis 中使用 Mapper 簡(jiǎn)化代碼的方法

    MyBatis 中使用 Mapper 簡(jiǎn)化代碼的方法

    這篇文章主要介紹了MyBatis 中使用 Mapper 簡(jiǎn)化代碼的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • 一文帶你掌握J(rèn)ava?Future模式的靈活應(yīng)用

    一文帶你掌握J(rèn)ava?Future模式的靈活應(yīng)用

    Future模式,簡(jiǎn)單來說,就是一種能夠管理異步操作的方式,它可以讓咱們的程序在執(zhí)行一個(gè)耗時(shí)任務(wù)的同時(shí),還能繼續(xù)做其他事情,下面我們就來看看Future模式的具體應(yīng)用吧
    2024-01-01
  • springMVC中@RequestParam和@RequestPart的區(qū)別

    springMVC中@RequestParam和@RequestPart的區(qū)別

    本文主要介紹了springMVC中@RequestParam和@RequestPart的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • Java 深入探究講解抽象工廠模式

    Java 深入探究講解抽象工廠模式

    當(dāng)系統(tǒng)所提供的工廠所需生產(chǎn)的具體產(chǎn)品并不是一個(gè)簡(jiǎn)單的對(duì)象,而是多個(gè)位于不同產(chǎn)品等級(jí)結(jié)構(gòu)中屬于不同類型的具體產(chǎn)品時(shí)需要使用抽象工廠模式,抽象工廠模式是所有形式的工廠模式中最為抽象和最具一般性的一種形態(tài)
    2022-04-04
  • Spring Boot 將yyyy-MM-dd格式的文本字符串直接轉(zhuǎn)換為L(zhǎng)ocalDateTime出現(xiàn)的問題

    Spring Boot 將yyyy-MM-dd格式的文本字符串直接轉(zhuǎn)換為L(zhǎng)ocalDateTime出現(xiàn)的問題

    這篇文章主要介紹了Spring Boot 將yyyy-MM-dd格式的文本字符串直接轉(zhuǎn)換為L(zhǎng)ocalDateTime出現(xiàn)的問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09

最新評(píng)論

绍兴市| 龙里县| 衢州市| 揭阳市| 疏勒县| 水富县| 乌拉特后旗| 剑川县| 桂东县| 金秀| 昆山市| 攀枝花市| 濉溪县| 荔波县| 兴城市| 孙吴县| 富平县| 桃园市| 台湾省| 玉山县| 横峰县| 三门县| 平潭县| 河东区| 新营市| 文昌市| 钟山县| 泗洪县| 偏关县| 安宁市| 衡东县| 达拉特旗| 竹溪县| 乌兰察布市| 太湖县| 蒙自县| 长葛市| 金平| 会泽县| 曲水县| 长武县|