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

JVM Metaspace內(nèi)存溢出問(wèn)題解決方案

 更新時(shí)間:2020年11月16日 09:27:38   作者:Java老K  
這篇文章主要介紹了JVM Metaspace內(nèi)存溢出排查總結(jié)過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

一. 現(xiàn)象

前段時(shí)間公司線上環(huán)境的一個(gè)Java應(yīng)用因?yàn)镺OM的異常報(bào)警,導(dǎo)致整個(gè)服務(wù)不可用被拉出集群,本地模擬重現(xiàn)的現(xiàn)象如下:


當(dāng)時(shí)的解決方案是增加metaspace的容量:-XX:MaxMetaspaceSize=500m,從原來(lái)默認(rèn)的256m改為500m,雖然沒(méi)有再出現(xiàn)oom,但這個(gè)只是臨時(shí)解決方案,通過(guò)公司的監(jiān)控系統(tǒng)觀察metaspace的使用情況還是在上升,而且后面隨著業(yè)務(wù)訪問(wèn)量越來(lái)越大還是有可能達(dá)到閾值。

二. 分析

Metaspace元空間主要是存儲(chǔ)類的元數(shù)據(jù)信息,我們的應(yīng)用里加載的各種類描述信息,比如類名、屬性、方法、訪問(wèn)限制等,按照一定的結(jié)構(gòu)存儲(chǔ)在Metaspace里。

由此可知metaspace空間增長(zhǎng)是由于反射類加載,動(dòng)態(tài)代理生成的類加載等導(dǎo)致的,也就是說(shuō)Metaspace的大小和加載類的數(shù)據(jù)有關(guān)系,加載的類越多metaspace占用的內(nèi)存也就越大。

因?yàn)榱私猱?dāng)時(shí)的業(yè)務(wù)場(chǎng)景是因?yàn)橛袀€(gè)郵件服務(wù)訪問(wèn)訂單詳情接口的訪問(wèn)量突然上升,以及查看log的eroor日志發(fā)現(xiàn)大部分都是訂單詳情接口先報(bào)出的這個(gè)問(wèn)題:java.lang.OutOfMemoryError: Metaspace


這里我在測(cè)試環(huán)境Java應(yīng)用的jvm里增加-XX:+TraceClassLoading -XX:+TraceClassUnloading記錄下類的加載和卸載情況,然后通過(guò)jmeter多個(gè)線程調(diào)用訂單詳情接口模擬metaspace溢出的現(xiàn)象,發(fā)現(xiàn)在catalina.out文件里輸出的除了業(yè)務(wù)上用到的類外還有大量的反射類,如下:


這些反射類被頻繁的加載和卸載是不正常的,通過(guò)Arthas診斷工具觀察調(diào)用鏈發(fā)現(xiàn)每次調(diào)用接口都是通過(guò)反射的方式實(shí)現(xiàn)的。


目前我們的項(xiàng)目都是基于SOA框架對(duì)外提供訪問(wèn)的,從上圖sun.reflect的調(diào)用者也能看出來(lái)


通過(guò)上圖可以看出在調(diào)用底層接口時(shí)都是通過(guò)反射的方式獲取類的實(shí)例,查看框架底層代碼實(shí)現(xiàn)可以確認(rèn)


同樣對(duì)底層接口返回的json數(shù)據(jù)反序列化時(shí)也會(huì)用到反射



繼續(xù)跟代碼可以看到這些反射的實(shí)現(xiàn)都會(huì)用到j(luò)ava.lang.Class里的ReflectionData對(duì)象


ReflectionData是個(gè)內(nèi)部靜態(tài)類被緩存起來(lái),里面的屬性就是我們做反射操作時(shí)需要用的屬性Field,方法Method和構(gòu)造函數(shù)等。但是有個(gè)問(wèn)題reflectionData是被SoftReference軟引用修飾的,如下圖


如果是軟引用的話在內(nèi)存空間不足時(shí)就可能會(huì)被回收掉,如果回收掉那下次再使用的話只能重新通過(guò)反射獲取。

而SoftReference是否被回收又跟SoftRefLRUPolicyMSPerMB參數(shù)的值有關(guān)系,查看我們線上JVM的配置發(fā)現(xiàn)XX:SoftRefLRUPolicyMSPerMB這個(gè)參數(shù)設(shè)置的是0


SoftRefLRUPolicyMSPerMB這個(gè)參數(shù)大概意思是每1M空閑空間可保持的SoftReference對(duì)象的生存時(shí)長(zhǎng)(單位是ms毫秒),LRU是Least Recently Used的縮寫,最近最少使用的。

這個(gè)值jvm默認(rèn)是1000ms,如果被設(shè)置為0,就會(huì)導(dǎo)致軟引用對(duì)象馬上被回收掉,進(jìn)而會(huì)導(dǎo)致重新頻繁的生成新的類,而無(wú)法達(dá)到復(fù)用的效果。

上圖里大量的sun.reflect.GeneratedSerializationConstructorAccessor,GeneratedMethodAccessor就是這樣產(chǎn)生的。

我把這個(gè)參數(shù)改回默認(rèn)值-XX:SoftRefLRUPolicyMSPerMB=1000 (1秒),發(fā)布到生產(chǎn)環(huán)境驗(yàn)證了下,發(fā)布后就降下來(lái)了,到今天為止基本上趨于穩(wěn)定


調(diào)整后基本上沒(méi)有再出現(xiàn)波動(dòng)

三. 總結(jié)

  • 目前主要是通過(guò)修改JVM的-XX:SoftRefLRUPolicyMSPerMB值來(lái)解決metaspace上升問(wèn)題,后續(xù)會(huì)持續(xù)觀察變化,適當(dāng)調(diào)整參數(shù)。至于這個(gè)參數(shù)之前為什么會(huì)被設(shè)置成0, 還需要找ops確認(rèn)下。
  • 我們的應(yīng)用需要大量RPC交互,屬于I/O密集型業(yè)務(wù),使用SOA,Dubbo都會(huì)遇到類似的問(wèn)題,通過(guò)上面的源碼分析可以看出這個(gè)是無(wú)法避免的(除非是換一種序列化協(xié)議,比如hessian,不走方法反射的方式來(lái)賦值)包括本身使用的Spring框架很多地方也是通過(guò)反射實(shí)現(xiàn)的比如AOP,還有我們埋點(diǎn)經(jīng)常使用的JsonUtils工具,通過(guò)dump文件也能看出來(lái)存在大量的屬性拷貝和反射操作。

所以我們?cè)谄綍r(shí)的業(yè)務(wù)代碼開(kāi)發(fā)中如果遇到兩個(gè)對(duì)象賦值的操作盡量少用反射的方式實(shí)現(xiàn),比如下面的代碼:


這里做的對(duì)象拷貝操作使用的是apache common-beanutils.jar中的BeanUtils,這個(gè)類底層采用javabeans+反射實(shí)現(xiàn),性能比較差,內(nèi)存開(kāi)銷比較大,當(dāng)系統(tǒng)高并發(fā)的情況容易導(dǎo)致Metaspace空間增長(zhǎng)過(guò)快,不建議這樣使用。

如果字段少的話直接賦值就行了,多的話可以使用Cglib的BeanCopier類,BeanCopier類底層是采用asm字節(jié)碼操作方式來(lái)進(jìn)行對(duì)象拷貝操作,性能損耗和內(nèi)存開(kāi)銷都比較小。

或者使用MapStruct這種幫你生成set、get方法的工具,效果會(huì)更好。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java中使用JWT生成Token進(jìn)行接口鑒權(quán)實(shí)現(xiàn)方法

    Java中使用JWT生成Token進(jìn)行接口鑒權(quán)實(shí)現(xiàn)方法

    這篇文章主要介紹了Java中使用JWT生成Token進(jìn)行接口鑒權(quán)實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • java中charAt()方法的使用及說(shuō)明

    java中charAt()方法的使用及說(shuō)明

    這篇文章主要介紹了java中charAt()方法的使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 學(xué)習(xí)Java之如何正確地跳出循環(huán)結(jié)構(gòu)

    學(xué)習(xí)Java之如何正確地跳出循環(huán)結(jié)構(gòu)

    我們?cè)诶醚h(huán)執(zhí)行重復(fù)操作的過(guò)程中,存在著一個(gè)需求:如何中止,或者說(shuō)提前結(jié)束一個(gè)循環(huán),所以就給大家講解一下,如何在java代碼中返回一個(gè)結(jié)果,如何結(jié)束和跳出一個(gè)循環(huán),需要的朋友可以參考下
    2023-05-05
  • Java語(yǔ)言中flush()函數(shù)作用及使用方法詳解

    Java語(yǔ)言中flush()函數(shù)作用及使用方法詳解

    這篇文章主要介紹了Java語(yǔ)言中flush函數(shù)作用及使用方法詳解,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • Java實(shí)現(xiàn)從jar包中讀取指定文件的方法

    Java實(shí)現(xiàn)從jar包中讀取指定文件的方法

    這篇文章主要介紹了Java實(shí)現(xiàn)從jar包中讀取指定文件的方法,涉及java針對(duì)jar文件的讀取及查找相關(guān)操作技巧,需要的朋友可以參考下
    2017-08-08
  • Java方法上注解值修改不成功的問(wèn)題

    Java方法上注解值修改不成功的問(wèn)題

    這篇文章主要介紹了Java方法上注解值修改不成功的解決方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02
  • 劍指Offer之Java算法習(xí)題精講數(shù)組與二叉樹(shù)

    劍指Offer之Java算法習(xí)題精講數(shù)組與二叉樹(shù)

    跟著思路走,之后從簡(jiǎn)單題入手,反復(fù)去看,做過(guò)之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化
    2022-03-03
  • 深入了解Java排序算法

    深入了解Java排序算法

    本文主要介紹了深入了解Java排序算法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2007-03-03
  • Java中controller層如何接收帶參數(shù)的查詢

    Java中controller層如何接收帶參數(shù)的查詢

    本文主要介紹了Java中controller層如何接收帶參數(shù)的查詢,在控制器層接收帶參數(shù)的查詢可以通過(guò)多種方式實(shí)現(xiàn),下面就詳細(xì)的介紹一下,感興趣的可以了解一下
    2023-08-08
  • Java Junit單元測(cè)試實(shí)例詳解

    Java Junit單元測(cè)試實(shí)例詳解

    在本篇文章里小編給大家分享的是關(guān)于Java Junit單元測(cè)試的相關(guān)知識(shí)點(diǎn)內(nèi)容,有興趣的朋友們學(xué)習(xí)下。
    2019-11-11

最新評(píng)論

苏尼特左旗| 阿瓦提县| 大余县| 巢湖市| 临武县| 河池市| 寿光市| 安福县| 温宿县| 沂水县| 朝阳市| 双柏县| 神农架林区| 宜兰县| 吉水县| 天峻县| 礼泉县| 岗巴县| 海口市| 什邡市| 松滋市| 宜城市| 呼玛县| 上犹县| 大冶市| 昂仁县| 镇安县| 疏勒县| 黔江区| 库尔勒市| 荣成市| 和政县| 鲁山县| 祥云县| 宿州市| 上饶县| 威宁| 襄垣县| 定西市| 庆云县| 莱西市|