JVM內(nèi)存泄漏之MaxDirectMemory

背景

樓主線上使用的是docker容器瘦黑,發(fā)現(xiàn)有比較多的容器退出乘客,container exited with a non-zero exit code 137袖瞻;google之后發(fā)現(xiàn)應(yīng)該是因為進(jìn)程oom導(dǎo)致的;https://www.containiq.com/post/exit-code-137走触;
樓主的配置:docker 12G 16Core主胧;jvm配置 -Xmx9G 叭首,查遍程序的日志沒發(fā)現(xiàn)oom的錯誤习勤,但docker的日志里也沒發(fā)現(xiàn)明顯的錯誤(郁悶)。

嘗試思路

1.開啟了jvm的 NMT 來搜集信息

開啟方式:-XX:NativeMemoryTracking=detail
使用方式參見別人的文檔:https://cloud.tencent.com/developer/article/1406522焙格;或者官方文檔https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html#BABIIIAC
說下我結(jié)論: 對比了程序啟動和一天之后的內(nèi)存使用图毕,heap,thread眷唉,code予颤,gc等幾個大模塊的內(nèi)存使用都比較正常,只有Internal模塊內(nèi)存增長不太對(啟動之初幾百M冬阳,第二天2.6G)蛤虐,可以確定的是Internal模塊使用的是堆外內(nèi)存;

Native Memory Tracking:

Total: reserved=14379MB +376MB, committed=13186MB +377MB

-                 Java Heap (reserved=8192MB, committed=8192MB)
                           (mmap: reserved=8192MB, committed=8192MB)

-                     Class (reserved=1137MB, committed=126MB)
                           (classes #19403 +9)
                           (malloc=3MB #42664 +262)
                           (mmap: reserved=1134MB, committed=123MB)

-                    Thread (reserved=1637MB +45MB, committed=1637MB +45MB)
                           (thread #1625 +45)
                           (stack: reserved=1630MB +45MB, committed=1630MB +45MB)
                           (malloc=5MB #8146 +225)
                           (arena=2MB #3236 +90)

-                      Code (reserved=258MB, committed=93MB +1MB)
                           (malloc=15MB #21645 +120)
                           (mmap: reserved=244MB, committed=78MB +1MB)

-                        GC (reserved=477MB +6MB, committed=477MB +6MB)
                           (malloc=141MB +6MB #175565 +134)
                           (mmap: reserved=336MB, committed=336MB)

-                  Compiler (reserved=4MB, committed=4MB)
                           (malloc=3MB #4926 +113)

-                  Internal (reserved=2619MB +325MB, committed=2619MB +325MB)
                           (malloc=2619MB +325MB #179961 +793)

-                    Symbol (reserved=26MB, committed=26MB)
                           (malloc=24MB #253198 +42)
                           (arena=2MB #1)

-    Native Memory Tracking (reserved=12MB, committed=12MB)
                           (malloc=1MB #11519 +2941)
                           (tracking overhead=11MB)

-               Arena Chunk (reserved=1MB, committed=1MB)
                           (malloc=1MB)

-                   Unknown (reserved=16MB, committed=0MB)
                           (mmap: reserved=16MB, committed=0MB)

[0x00007fc68e2ad16a] Unsafe_AllocateMemory+0xfa
[0x00007fc67a40aea8]
                            (malloc=1684MB type=Internal +320MB #1665 +29)
# 重要: 注意此處internal 分配了1.6G肝陪,跟我設(shè)置的baseline比較增長了320M驳庭,分配次數(shù)29次;

[0x00007fc68e24fac5] ObjectSynchronizer::omAlloc(Thread*)+0x6c5
[0x00007fc68e24fda5] ObjectSynchronizer::inflate(Thread*, oopDesc*)+0x255
[0x00007fc68e250ec6] ObjectSynchronizer::fast_enter(Handle, BasicLock*, bool, Thread*)+0x76
[0x00007fc68e1dfc0c] SharedRuntime::complete_monitor_locking_C(oopDesc*, BasicLock*, JavaThread*)+0x6c
                            (malloc=11MB type=Internal +2MB #497 +76)

[0x00007fc68e24fac5] ObjectSynchronizer::omAlloc(Thread*)+0x6c5
[0x00007fc68e24fbb0] ObjectSynchronizer::inflate(Thread*, oopDesc*)+0x60
[0x00007fc68e250ec6] ObjectSynchronizer::fast_enter(Handle, BasicLock*, bool, Thread*)+0x76
[0x00007fc68e1dfc0c] SharedRuntime::complete_monitor_locking_C(oopDesc*, BasicLock*, JavaThread*)+0x6c
                            (malloc=16MB type=Internal +3MB #756 +138)

注意上面這一段:
[0x00007fc68e2ad16a] Unsafe_AllocateMemory+0xfa <--- 分配內(nèi)存的調(diào)用方法
[0x00007fc67a40aea8]
(malloc=1684MB type=Internal +320MB #1665 +29)
意思是internal 分配了1.6G(剛啟動才幾百兆)氯窍,跟我設(shè)置的baseline比較增長了320M饲常,分配次數(shù)29次;
從調(diào)用方可知Unsafe_AllocateMemory 這個方法申請的狼讨;查了我的程序贝淤,沒有發(fā)現(xiàn)調(diào)用的地方;擴(kuò)大范圍搜索依賴的三方庫政供,發(fā)現(xiàn)couchbase的client依賴了netty播聪,而netty作為一個優(yōu)秀的io框架,為了保證性能布隔,有在操作direct memory.

至此:可以大膽猜測是它造成的离陶,雖然沒有確鑿證據(jù),但是只有它在調(diào)用unsafe.allocateMemory .
于是去查了下direct memory的默認(rèn)大小执泰,如下:

-XX:MaxDirectMemorySize
-XX:MaxDirectMemorySize=size 用于設(shè)置 New I/O (java.nio) direct-buffer allocations 的最大大小枕磁,size 的單位可以使用 k/K渡蜻、m/M术吝、g/G;如果沒有設(shè)置該參數(shù)則默認(rèn)值為 0茸苇,意味著 JVM 自己自動給 NIO direct-buffer allocations 選擇最大大小排苍,從代碼 java.base/jdk/internal/misc/VM.java 中可以看到默認(rèn)是取的 Runtime.getRuntime ().maxMemory ()

在沒有配置的情況下,最大等于Xmx学密,確實比較危險淘衙。

2.尋找佐證

發(fā)現(xiàn)一篇非常有價值的博客,源地址:https://www.cnblogs.com/dengq/p/13687423.html 腻暮,主要內(nèi)容貼上:

1) Java_JVM參數(shù)-XX:MaxDirectMemorySize

JVM堆內(nèi)存大小可以通過-Xmx來設(shè)置彤守,同樣的direct ByteBuffer可以通過-XX:MaxDirectMemorySize來設(shè)置毯侦,此參數(shù)的含義是當(dāng)Direct ByteBuffer分配的堆外內(nèi)存到達(dá)指定大小后,即觸發(fā)Full GC具垫。注意該值是有上限的侈离,默認(rèn)是64M,最大為sun.misc.VM.maxDirectMemory()筝蚕,在程序中中可以獲得-XX:MaxDirectMemorySize的設(shè)置的值卦碾。
1.2.2、沒有配置MaxDirectMemorySize的起宽,因此MaxDirectMemorySize的大小即等于-Xmx
1.2.3洲胖、Direct Memory的回收機(jī)制,Direct Memory是受GC控制的
1.2.4坯沪、對于使用Direct Memory較多的場景绿映,需要注意下MaxDirectMemorySize的設(shè)置,避免-Xmx + Direct Memory超出物理內(nèi)存大小的現(xiàn)象

2)用JDK8的一定要配置:-Xms -Xmx -XX:MaxDirectMemorySize腐晾,【Xmx +(加) MaxDirectMemorySize】的值不能超過docker的最大內(nèi)存绘梦,不然docker內(nèi)存占滿了會被oomkill掉;**

 沒配置參數(shù)導(dǎo)致的問題以及處理參考:[http://hellojava.info/?tag=maxdirectmemorysize](http://hellojava.info/?tag=maxdirectmemorysize) ([物理內(nèi)存耗盡赴魁、CMS GC碎片造成RT慢的兩個Case](http://hellojava.info/?p=188))
分析:[https://my.oschina.net/go4it/blog/3029481](https://my.oschina.net/go4it/blog/3029481)

其他:看到一個有用的java排障地址卸奉,收藏下https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/index.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市颖御,隨后出現(xiàn)的幾起案子榄棵,更是在濱河造成了極大的恐慌,老刑警劉巖潘拱,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疹鳄,死亡現(xiàn)場離奇詭異,居然都是意外死亡芦岂,警方通過查閱死者的電腦和手機(jī)瘪弓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來禽最,“玉大人腺怯,你說我怎么就攤上這事〈ㄎ蓿” “怎么了呛占?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長懦趋。 經(jīng)常有香客問我晾虑,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任帜篇,我火速辦了婚禮糙捺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘笙隙。我一直安慰自己继找,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布逃沿。 她就那樣靜靜地躺著婴渡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪凯亮。 梳的紋絲不亂的頭發(fā)上边臼,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音假消,去河邊找鬼柠并。 笑死,一個胖子當(dāng)著我的面吹牛富拗,可吹牛的內(nèi)容都是我干的臼予。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼啃沪,長吁一口氣:“原來是場噩夢啊……” “哼粘拾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起创千,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤缰雇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后追驴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體械哟,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年殿雪,在試婚紗的時候發(fā)現(xiàn)自己被綠了暇咆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡丙曙,死狀恐怖爸业,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情河泳,我是刑警寧澤沃呢,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站拆挥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜纸兔,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一惰瓜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧汉矿,春花似錦崎坊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赋续,卻和暖如春男翰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纽乱。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工蛾绎, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鸦列。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓租冠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親薯嗤。 傳聞我的和親對象是個殘疾皇子顽爹,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容