在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Java應用OOM問題的排查過程

OSC開源社區 ? 來源:OSC開源社區 ? 2025-02-12 11:15 ? 次閱讀

導讀

本文記錄最近一例Java應用OOM問題的排查過程,希望可以給遇到類似問題的同學提供參考。

前言:此文記錄最近一例Java應用OOM問題的排查過程,希望可以給遇到類似問題的同學提供參考。在本地集團,大多數情況下Java堆的大小會設置為容器規格的50%~70%,但如果你設置為50%時還是遇到了OS OOM的問題,會不會無法忍受進而想要知道這是為什么?沒錯,我也有一樣的好奇。

背景

某核心應用的負責同學反饋應用存在少量機器OOM被OS kill的問題。看sunfire監控信息,的確如此。

8b862c70-e854-11ef-9310-92fbcf53809c.jpg

8b97f39c-e854-11ef-9310-92fbcf53809c.jpg

初步收集到的信息:

容器內存=8G,Java 11,G1 GC=4G,MaxDirectMemorySize=1G。詳見下圖:

8baf1ad6-e854-11ef-9310-92fbcf53809c.jpg

業務同學已經做過Java dump,可以看到堆外對象幾乎沒有,堆內的使用量也不大,<3G。上機器查看Java進程的內存使用量的確很大:

8bc65cdc-e854-11ef-9310-92fbcf53809c.jpg

通過目前掌握到的信息來看,4G(Java堆)+1G(堆外)+512M(元空間)+250M(CodeCache)+其它,離6.8G還是有不少差距,無法簡單的明確原因,需要深入排查分析了。

問題結論

省流版

中間件中多個不同的ClassLoader加載了多個netty的io.netty.buffer.PooledByteBufAllocator,每一個都有1G的內存配額,所以存在實際使用的堆外內存超出1G限制的問題。

通過Arthas可以看到存在這個類的7個不同的實例:

8bdd836c-e854-11ef-9310-92fbcf53809c.jpg

而其中rocketmq-client的這一個,已經基本用完1G的內存(其它幾個使用量大多在100多M的樣子):

8bf08cbe-e854-11ef-9310-92fbcf53809c.jpg

詳細版

中間件中多個不同的ClassLoader加載了多個netty的io.netty.buffer.PooledByteBufAllocator,每個Allocator都用自己的計數器在限制堆外內存的使用量,這個限制值大多數情況下取值至MaxDirectMemorySize,所以會存在無法限制堆外內存使用量在1G以內的問題。(這個設計是否合理,還請中間件的同學幫忙補充了)

這個應用是餓了么彈內的應用,io.netty.buffer.PooledByteBufAllocator,有7個ClassLoader加載了它,分別是:

sentinel's ModuleClassLoader、rocketmq-client's ModuleClassLoader、tair-plugin's ModuleClassLoader、hsf's ModuleClassLoader、XbootModuleClassLoader、pandora-qos-service's ModuleClassLoader、ele-enhancer's ModuleClassLoader。

相比彈內應用的4個(數據來自淘天集團的核心應用ump2,如下圖),多了3個。

8c08090c-e854-11ef-9310-92fbcf53809c.jpg

在Java8,以及Java11中(JVM參數設置了-Dio.netty.tryReflectionSetAccessible=true過后),netty會直接使用unsafe的方法申請堆外內存,不通過Java的DirectMemory分配API,所以通過監控看不到堆外內存的占用量,也不受JVM MaxDirectMemorySize的管控。

查看DirectByteBuffer實現代碼可以發現,它限制MaxDirectMemorySize的方法是在Java層(代碼標記處1),實際上在JVM底層是沒有任何限制的,netty是直接用了這里代碼標記處2的API分配內存。

8c1ac1f0-e854-11ef-9310-92fbcf53809c.jpg

排查過程

1.1.通過NativeMemoryTracking看Native內存的占用分布

通過在JVM參數上加上-XX:NativeMemoryTracking=detail,就可以打印出詳細的內存分類的占用信息了,觀察了一整天,發現主要的可疑變化是在Other部分,即堆外的部分,如下圖。( Java NMT的詳細使用可以參考相應的技術文章)

8c346c5e-e854-11ef-9310-92fbcf53809c.jpg

明明是限制的堆外1G,怎么超過了這么多。再多觀察一會,發現它還會繼續緩慢上漲的,最高達到接近1.5GB。這就和最開始查看Java進程的RSS占用對上了。

1.2.native內存泄漏了嗎

JVM使用什么native分配器

通過查看機器上安裝的JDK的信息,可以看到使用的是jemalloc的內存分配器。是不是它有泄漏、內存碎片、歸還不及時的問題?

網上搜索,發現的有一篇文章講的場景和我們這里的有一些類似。(https://blog.csdn.net/liulilittle/article/details/137535634)

嘗試重新下載jemalloc的源碼,并進行其參數的調整:

export MALLOC_CONF="dirty_decay_ms:0,muzzy_decay_ms:0"

觀察發現內存的占用量有少量的下降,但還是會超過1個G,看起來核心問題不在這里。

誰在分配內存

同時還通過perf工具監控了下調用內存分配的調用棧,想看看有什么線索沒有,然而并沒有什么線索。畢竟這個內存的增長比較緩慢,perf也不可能抓太長時間了,遂放棄這個思路。

sudo perf probe -x /opt/taobao/install/ajdk11_11.0.23.24/lib/libjemalloc.so.2 malloc

sudo perf record -e probe_libjemalloc:malloc -p `pidof java` -g -- sleep 10

8c54da66-e854-11ef-9310-92fbcf53809c.jpg

內存里面裝了什么

通過 sudo pmap -x `pidof java` | sort -k 3 -n 命令查看進程的所有內存塊信息,如下圖示:

8c75f3ae-e854-11ef-9310-92fbcf53809c.jpg

排除最大的4G的這一個(這是Java堆),以及內存標志帶x的兩個(可執行代碼標志,那是CodeCache),把其它的塊都dump下來,看看里面都放了啥,有沒有什么不平凡的。

使用gdb命令:gdb --batch --pid `pidof java` -ex "dump memory mem1.log 0x7f0109800000 0x7f0109800000+0x200000"

然后將dump下的內存以字符串的方式輸出觀察下:cat mem1.log | strings

8c9331a8-e854-11ef-9310-92fbcf53809c.jpg

8ca9e1f0-e854-11ef-9310-92fbcf53809c.jpg

如圖所示,發現里面大量的內容都和RocketMQ有關。不過我發現我早率了,這些dump內容我看了快一天,根本沒有發現什么不太對的地方,看起來都是正常的占用。(不過明顯能看出來這里面存了一堆消費者信息,表達的比較冗余)

求助JVM專家

還真是從入門到放棄,到這個時候已經沒啥信心啦。遂求助于JVM的專家毛亮,他給了大的方向,一是這里不太可能有native的內存泄漏,二是既然懷疑是堆外,把堆外內存減少一點看看情況,明確下是不是native內存分配器的回收特性就是這樣。往往native的內存分配器都有自己的管理策略,他會有自己的回收拐點,比應用看到的高一點是合理的。

的確,那么接下來的策略就是把MaxDirectMemeorySize調低到512M觀察下效果吧。

1.3.堆外內存調小影響業務了

在堆外內存從1G調小到512M過后,過了個周末,周一的時候業務同學就反饋,調小遇到問題了,存在MQ消息消費不及時而導致消息擠壓的問題。結合之前看到的native內存的信息,突然想到,MQ客戶端一定是占用了超過512M的內存,內心里出現了兩個問題:

1.MQ底層依賴netty,那么netty實際使用的內存是多少?以及這個內存占用量和native的堆外占用量是什么關系?

2.為啥Java的DirectMemory占用這么少,netty的內存占用似乎并沒有被看到,這是怎么回事?

帶著這兩個問題,查看了netty內存管理的核心類 io.netty.buffer.PooledByteBufAllocator,以及機器上啟動過程中打印出的信息。

8cbe0a68-e854-11ef-9310-92fbcf53809c.jpg

結合這里面涉及的另一個核心類io.netty.util.internal.PlatformDependent,大概明白了這里面的邏輯,netty是直接使用(是有前提條件的,但這個應用通過JVM參數[-Dio.netty.tryReflectionSetAccessible=true]開啟了這個特性,這也是大多數應用上面的行為)UNSAFE.allocateMemory分配內存,完全繞過Java的直接內存API。然后它自己實現了內存占用空間的限制,這個值等于JVM參數中的MaxDirectMemorySize。到這里,似乎發現了曙光,莫非就是netty?(netty這么做的原因是為了不依賴JVM機制而加速內存的釋放,同時也是為了解決在堆外內存不足時JVM的糟糕的回收機制設計。)

1.4.Netty到底占用了多少內存

好在netty的類中有一個靜態變量是可以很容易的看到這個信息的:

io.netty.buffer.PooledByteBufAllocator#DEFAULT。

那么這個時候就是需要上機器去執行它了。Arthas是個不錯的工具,可以直接在機器執行表達式看任何靜態變量的值,并不需要我們改代碼然后去調用上面的對象做日志打印。

登錄機器后,通過命令查找netty Allocator的類定義:

sc -d io.netty.buffer.PooledByteBufAllocator

8cd200a4-e854-11ef-9310-92fbcf53809c.jpg

發現有不止一個Allocator,來自于不同的ClassLoader,以及不同的jar包。一共有7個。

然后一個一個的看他們實際占用的大小:

getstatic -c d5bc00 io.netty.buffer.PooledByteBufAllocator DEFAULT

8cda38e6-e854-11ef-9310-92fbcf53809c.jpg

8cf15dc8-e854-11ef-9310-92fbcf53809c.jpg

然后把他們占用的內存逐項加起來,發現的確超過了1G,同時和前面通過NMT看到的Other類別的內存大小是比較吻合的。到這里大概就明確具體是怎么回事了,內存是netty用掉的。

1.5.業務應該怎么做呢

到目前為此,問題是明確了,但似乎并沒有什么太好的解法。一個是rocketmq-client的內存占用是不是太大了,有沒有什么可以優化的地方?(從前面看native內存看到的內容來看,還是有很大的優化空間的,一大堆地址信息都是以字符串的形式寫在內存里面),另一個是中間件的調整肯定是長期的,短期業務要怎么辦呢?

思考再三,短期來看只能是先讓業務把Java堆調小(通過Java dump以及JVM監控可以看出來堆的使用率并不高),來適應當前的現狀了。

至于堆外內存大小沒有限制住的問題,我感覺并不是中間件同學的預期之中的,這塊后面也找相關同學聊一聊。

后記

以后排查Java堆外內存過大的問題,優先看netty的占用。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內存
    +關注

    關注

    8

    文章

    3068

    瀏覽量

    74389
  • JAVA
    +關注

    關注

    19

    文章

    2977

    瀏覽量

    105227

原文標題:8G的容器Java堆才4G怎么就OOM了?

文章出處:【微信號:OSC開源社區,微信公眾號:OSC開源社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Java 23功能介紹

    Java 23 包含全新和更新的 Java 語言功能、核心 API 以及 JVM,同時適合新的 Java 開發者和高級開發者。從?IntelliJ IDEA 2024.2?開始已支持 Java
    的頭像 發表于 12-04 10:02 ?382次閱讀
    <b class='flag-5'>Java</b> 23功能介紹

    焊接機器人常見故障及排查

    的跡象。 檢查緊固件: 確保所有緊固件都已正確擰緊,沒有松動。 檢查過載保護: 如果機器人有過載保護,檢查是否因為過載而停止工作。 2. 電氣故障 故障現象: 機器人無法啟動、電機不工作、控制柜指示燈異常等。 排查方法: 檢查電源: 確保電
    的頭像 發表于 11-25 09:50 ?699次閱讀

    Java集合API的改進介紹

    解答這些問題。 我們將逐步學習 Java 集合類的優化過程,并按版本逐一對比分析。主要討論的焦點將包括 JDK 1.0、1.2、1.4、1.5、1.6、1.8、9、10、11 和 21 版本的 Java 集合功能
    的頭像 發表于 11-22 11:12 ?271次閱讀
    <b class='flag-5'>Java</b>集合API的改進介紹

    Java中時間戳的使用

    Java中時間戳的使用
    的頭像 發表于 11-06 16:04 ?275次閱讀
    <b class='flag-5'>Java</b>中時間戳的使用

    java反編譯能拿到源碼嗎

    Java反編譯是一種將編譯后的Java字節碼(.class文件)轉換回Java源代碼的過程。雖然反編譯可以幫助理解代碼的邏輯和結構,但它并不總是能完美地還原原始源代碼。反編譯工具通常會
    的頭像 發表于 09-02 11:03 ?1211次閱讀

    光纖故障怎么排查

    光纖故障的排查是一個細致且系統的過程,涉及多個方面的檢查和測試。以下是一系列光纖故障排查的步驟和方法: 一、初步檢查 確認物理連接:首先檢查光纖網絡的物理連接是否正常,包括光纖端口是否正確連接到設備
    的頭像 發表于 08-20 10:25 ?1363次閱讀

    java淺拷貝BeanUtils.copyProperties引發的RPC異常

    java.lang.ClassCastException: java.util.HashMap cannot be cast to cn.xxx.xxx.xxx.xxx.BatchInfo 排查過程
    的頭像 發表于 08-13 17:11 ?316次閱讀
    <b class='flag-5'>java</b>淺拷貝BeanUtils.copyProperties引發的RPC異常

    華納云:java web和java有什么區別java web和java有什么區別

    Java Web和Java是兩個不同的概念,它們在功能、用途和實現方式上存在一些區別,下面將詳細介紹它們之間的區別。 1. 功能和用途: – Java是一種編程語言,它提供了一種用于開發各種應用程序
    的頭像 發表于 07-16 13:35 ?931次閱讀
    華納云:<b class='flag-5'>java</b> web和<b class='flag-5'>java</b>有什么區別<b class='flag-5'>java</b> web和<b class='flag-5'>java</b>有什么區別

    記錄一次使用easypoi時與源碼博弈的過程

    。 二、問題描述 一線之聲在事件查詢菜單下支持將結果導出為Excel,程序中使用easypoi+apache-poi實現,此功能一直正常使用,直到從2024-04-12 12.04.39之后的任務全部都導出失敗 ?? ? 三、問題定位 3.1 排查過程 看到這個問題后,第一反應是不是某次
    的頭像 發表于 07-03 16:33 ?411次閱讀
    記錄一次使用easypoi時與源碼博弈的<b class='flag-5'>過程</b>

    電纜故障排查技術案例筆記

    電纜故障排查技術案例筆記
    的頭像 發表于 05-20 17:03 ?663次閱讀
    電纜故障<b class='flag-5'>排查</b>技術案例筆記

    已經安裝了Java,且依然提示安裝Java是為什么?

    我已經在機器上安裝了最新版的 Java 10,打開 Cube 卻得到要求安裝 Java 1.7.0_45 的提示。何解?Eclipse CDT 依賴 Java,不可卸載重裝。
    發表于 04-26 06:23

    深入理解Java 8內存管理機制及故障排查實戰指南

    Java的自動內存管理機制是由 JVM 中的垃圾收集器來實現的,垃圾收集器會定期掃描堆內存中的對象,檢測并清除不再使用的對象,以釋放內存資源。
    的頭像 發表于 04-04 08:10 ?1068次閱讀
    深入理解<b class='flag-5'>Java</b> 8內存管理機制及故障<b class='flag-5'>排查</b>實戰指南

    一根網線引發的問題:PLC程序下載失敗排查攻略

    排查過程中,我注意到了一個奇怪的現象:在監控程序時,有時會出現不同步的情況。明明之前還是正常的綠色符號,下拉到其他程序段時卻消失了。
    發表于 03-25 14:18 ?2090次閱讀
    一根網線引發的問題:PLC程序下載失敗<b class='flag-5'>排查</b>攻略

    CPU 100%問題怎么排查?有哪些方法?

    首先,先用放之四海而皆準的命令 top,確認一下是不是 Java 進程是罪魁禍首。Java 進程要不然就是個后臺任務,要不然就是個 jar 包,比如一個Spring Boot 服務。
    的頭像 發表于 03-18 17:09 ?9072次閱讀
    CPU 100%問題怎么<b class='flag-5'>排查</b>?有哪些方法?

    STM32G0B1CCT6休眠喚醒后ADC不能ready怎么解決?

    休眠喚醒后ADC_ISR的Bit 0 ADRDY: ADC ready一直為0,是偶發現象,是可能什么原因造成的呀,這塊調用的while檢查過了是沒有問題的,有人能提供下排查思路嗎,感謝!!!
    發表于 03-11 07:09
    主站蜘蛛池模板: 综合激情在线 | 亚洲综合在线观看一区www | 狠狠狠狠干| 免费国产一区二区三区 | 好男人社区www在线观看 | 又色又爽视频 | 狠狠干.com | 在线观看精品视频看看播放 | 天天爆操 | a一级视频 | 亚洲一本之道在线观看不卡 | 午夜影院404| 亚洲区 欧美区 | 亚欧洲乱码专区视频 | 久久久久久人精品免费费看 | 欧美网站在线 | 国产看色免费 | 色校园| 国产视频三级 | 高清视频一区 | 国产主播精品在线 | 黑人又大又粗又长又深受不了 | 五月天婷婷在线观看 | 美女被免网站在线视频 | 人人澡人人射 | 国产色视频网站免费观看 | 高清在线观看视频 | 大又大又粗又爽又黄毛片女人 | 欧美成人3d动漫在线播放网站 | 亚洲一区二区三区在线 | 免费观看一级一片 | 国内在线观看精品免费视频 | 免费视频在线看 | japanese色系国产在线高清 | 天堂网www天堂在线资源链接 | 午夜老司机福利 | 久久男人视频 | 欧美性猛交xxxx乱大交高清 | 在线观看深夜观看网站免费 | 久色网| 久久毛片视频 |