亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

 更新時(shí)間:2020年11月16日 09:27:38   作者:Java老K  
這篇文章主要介紹了JVM Metaspace內(nèi)存溢出排查總結(jié)過程圖解,文中通過示例代碼介紹的非常詳細(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,從原來默認(rèn)的256m改為500m,雖然沒有再出現(xiàn)oom,但這個(gè)只是臨時(shí)解決方案,通過公司的監(jiān)控系統(tǒng)觀察metaspace的使用情況還是在上升,而且后面隨著業(yè)務(wù)訪問量越來越大還是有可能達(dá)到閾值。

二. 分析

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

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

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


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


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


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


通過上圖可以看出在調(diào)用底層接口時(shí)都是通過反射的方式獲取類的實(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)類被緩存起來,里面的屬性就是我們做反射操作時(shí)需要用的屬性Field,方法Method和構(gòu)造函數(shù)等。但是有個(gè)問題reflectionData是被SoftReference軟引用修飾的,如下圖


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

而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)致重新頻繁的生成新的類,而無法達(dá)到復(fù)用的效果。

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

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


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

三. 總結(jié)

  • 目前主要是通過修改JVM的-XX:SoftRefLRUPolicyMSPerMB值來解決metaspace上升問題,后續(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ì)遇到類似的問題,通過上面的源碼分析可以看出這個(gè)是無法避免的(除非是換一種序列化協(xié)議,比如hessian,不走方法反射的方式來賦值)包括本身使用的Spring框架很多地方也是通過反射實(shí)現(xiàn)的比如AOP,還有我們埋點(diǎn)經(jīng)常使用的JsonUtils工具,通過dump文件也能看出來存在大量的屬性拷貝和反射操作。

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


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

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

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

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

相關(guān)文章

  • 淺談Java中ArrayList的擴(kuò)容機(jī)制

    淺談Java中ArrayList的擴(kuò)容機(jī)制

    本文主要介紹了淺談Java中ArrayList的擴(kuò)容機(jī)制,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • java實(shí)現(xiàn)服務(wù)器文件打包zip并下載的示例(邊打包邊下載)

    java實(shí)現(xiàn)服務(wù)器文件打包zip并下載的示例(邊打包邊下載)

    這篇文章主要介紹了java實(shí)現(xiàn)服務(wù)器文件打包zip并下載的示例,使用該方法,可以即時(shí)打包文件,一邊打包一邊傳輸,不使用任何的緩存,讓用戶零等待,需要的朋友可以參考下
    2014-04-04
  • java中object類實(shí)例分析

    java中object類實(shí)例分析

    這篇文章主要介紹了java中object類實(shí)例分析,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12
  • Mybatis+Druid+MybatisPlus多數(shù)據(jù)源配置方法

    Mybatis+Druid+MybatisPlus多數(shù)據(jù)源配置方法

    在項(xiàng)目開發(fā)中,經(jīng)常需要連接多個(gè)數(shù)據(jù)庫(kù),使用Mybatis、Druid和MybatisPlus可以實(shí)現(xiàn)多數(shù)據(jù)源配置,通過定義配置類和修改配置文件,如properties或yaml,可以設(shè)置多個(gè)數(shù)據(jù)源,本文介紹了配置項(xiàng)包括Druid基本配置、數(shù)據(jù)源一、數(shù)據(jù)源二,感興趣的朋友一起看看吧
    2024-09-09
  • Java編寫緩存工具類的示例代碼

    Java編寫緩存工具類的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何基于Java編寫一個(gè)緩存工具類,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴可以了解一下
    2023-07-07
  • 一文帶你厲害Java設(shè)計(jì)模式中的模板方法

    一文帶你厲害Java設(shè)計(jì)模式中的模板方法

    模板方法定義了一個(gè)算法的步驟,并允許子類為一個(gè)或多個(gè)步驟提供實(shí)現(xiàn)。這篇文章就來帶大家了解一下Java模板方法的概念與實(shí)現(xiàn),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-01-01
  • Java簡(jiǎn)單實(shí)現(xiàn)對(duì)一串?dāng)?shù)字采用相應(yīng)的加密策略后傳輸

    Java簡(jiǎn)單實(shí)現(xiàn)對(duì)一串?dāng)?shù)字采用相應(yīng)的加密策略后傳輸

    下面小編就為大家?guī)硪黄狫ava簡(jiǎn)單實(shí)現(xiàn)對(duì)一串?dāng)?shù)字采用相應(yīng)的加密策略后傳輸。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-09-09
  • mybatis?實(shí)現(xiàn)字段大小寫賦值

    mybatis?實(shí)現(xiàn)字段大小寫賦值

    這篇文章主要介紹了mybatis?實(shí)現(xiàn)字段大小寫賦值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java編程中的性能優(yōu)化如何實(shí)現(xiàn)

    Java編程中的性能優(yōu)化如何實(shí)現(xiàn)

    這篇文章主要介紹了Java編程中的性能優(yōu)化如何實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • 解決SpringBoot項(xiàng)目中l(wèi)og4j與logback的Jar包沖突問題

    解決SpringBoot項(xiàng)目中l(wèi)og4j與logback的Jar包沖突問題

    這篇文章主要給大家介紹了解決SpringBoot項(xiàng)目中l(wèi)og4j與logback的Jar包沖突問題,文中有詳細(xì)的解決方法和沖突的原因,有遇到相同問題的朋友可以參考閱讀本文
    2023-10-10

最新評(píng)論