欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

一. 現(xiàn)象

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


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

二. 分析

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

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

因為了解當(dāng)時的業(yè)務(wù)場景是因為有個郵件服務(wù)訪問訂單詳情接口的訪問量突然上升,以及查看log的eroor日志發(fā)現(xiàn)大部分都是訂單詳情接口先報出的這個問題:java.lang.OutOfMemoryError: Metaspace


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


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


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


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


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



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


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


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

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


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

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

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

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


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

三. 總結(jié)

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

所以我們在平時的業(yè)務(wù)代碼開發(fā)中如果遇到兩個對象賦值的操作盡量少用反射的方式實現(xiàn),比如下面的代碼:


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

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

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

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

相關(guān)文章

  • 淺談Java中ArrayList的擴容機制

    淺談Java中ArrayList的擴容機制

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

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

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

    java中object類實例分析

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新評論