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

jvm堆外內(nèi)存排查圖文舉例詳解

 更新時(shí)間:2023年12月15日 09:27:02   作者:Xd聊架構(gòu)  
Java應(yīng)用程序通過(guò)直接方式從操作系統(tǒng)中申請(qǐng)的內(nèi)存,叫堆外內(nèi)存,這篇文章主要給大家介紹了關(guān)于jvm堆外內(nèi)存排查的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

內(nèi)存泄漏想必大家并不陌生,對(duì)于jvm的內(nèi)存泄漏,有很多排查手段和方便的排查工具,例如MAL,但是對(duì)于非jvm的內(nèi)存,如直接內(nèi)存的使用,排查起來(lái)較為麻煩,下面介紹一下相關(guān)的排查手段

一、堆外內(nèi)存排查

1.背景

在一次內(nèi)存檢查的過(guò)程中,意外發(fā)現(xiàn)在linux的java進(jìn)程內(nèi)存占用,遠(yuǎn)高于jvm的內(nèi)存設(shè)定最大值(堆+非堆),第一時(shí)間是考慮java可以采用直接內(nèi)存,如mmap對(duì)內(nèi)存進(jìn)行使用,但經(jīng)過(guò)排查,發(fā)現(xiàn)并非如此,下面看一下排查過(guò)程

2.內(nèi)存對(duì)比

首先通過(guò)top,可以看到j(luò)ava進(jìn)行使用了4.2g的內(nèi)存,且pid為2730

ps -ef|grep java
top -pid 2730

因?yàn)槲抑牢业膉vm最大內(nèi)存設(shè)置為3G左右,所以第一時(shí)間就沒有去看JVM的最大值,如果不確定,優(yōu)先查看JVM的堆、非堆的內(nèi)存分配情況,本次忽略,直接查看NMT。

為了觀察java進(jìn)程堆外內(nèi)存的占用,JVM啟動(dòng)參數(shù)中添加參數(shù):-XX:NativeMemoryTracking=summary,這個(gè)參數(shù)對(duì)jvm可能會(huì)有5%左右的性能損耗,所以生產(chǎn)環(huán)境不推薦開啟。

同時(shí),-XX:+DisableExplicitGC:禁止顯示GC,即代碼中聲明的 System.gc();//建議jvm進(jìn)行g(shù)c 不再生效。在jdk源碼中使用nio申請(qǐng)堆外內(nèi)存時(shí),堆外內(nèi)存不足時(shí)會(huì)執(zhí)行 System.gc() 進(jìn)行堆外內(nèi)存的回收,所以,堆外內(nèi)存使用較多時(shí)不推薦配置 -XX:+DisableExplicitGC。

最后,為了防止堆外內(nèi)存的溢出,jvm啟動(dòng)參數(shù)可以換添加:-XX:MaxDirectMemorySize=1024M

開啟NMT后,通過(guò)jcmd命令查看內(nèi)存情況

jcmd 2730 VM.native_memory scale=MB

Heap(堆)、Class(元空間)、Thread(java線程棧,含GC本地線程)、Code(本地字節(jié)碼,即JIT存儲(chǔ)熱點(diǎn)代碼地方)、GC(JVM GC額外占用的,例如G1中的Remembered Set等數(shù)據(jù)結(jié)構(gòu))、Internal(Direct Buffer直接內(nèi)存,例如nio)等占用。Native Memory Tracking表示該功能自身占用的部分。

JVM 的內(nèi)存大致分為下面這幾個(gè)部分:

  • 堆(Heap):young、old 區(qū)域等
  • 線程棧(Thread Stack):每個(gè)線程棧預(yù)留 1M 的線程棧大小
  • 非堆(Non-heap):包括 code_cache、metaspace 等
  • 堆外內(nèi)存:unsafe.allocateMemory 和 DirectByteBuffer 申請(qǐng)的堆外內(nèi)存
  • native (C/C++ 代碼)申請(qǐng)的內(nèi)存
  • 還有 JVM 運(yùn)行本身需要的內(nèi)存,比如 GC 等

可以看到JVM只使用了3G左右,其中Internal的39M為直接內(nèi)存的使用,那么剩余的1.2G非JVM的使用。因?yàn)閖cmd命令顯示的內(nèi)存包含堆內(nèi)內(nèi)存、Code區(qū)域、通過(guò)unsafe.allocateMemory和DirectByteBuffer申請(qǐng)的內(nèi)存,但是不包含其他Native Code(C代碼)申請(qǐng)的堆外內(nèi)存。所以猜測(cè)是使用Native Code申請(qǐng)內(nèi)存所導(dǎo)致的問(wèn)題。

其他jcmd可用命令:

查看java進(jìn)程內(nèi)存占用詳細(xì)情況(-XX:NativeMemoryTracking=summary,關(guān)閉NMT命令:jcmd pid VM.native_memory shutdown):
jcmd pid VM.native_memory scale=MB
 
保存java進(jìn)程內(nèi)存占用情況的基準(zhǔn)版本:
jcmd pid VM.native_memory scale=MB baseline
 
與基準(zhǔn)版本進(jìn)行比較(若懷疑存在內(nèi)存泄漏,可過(guò)段時(shí)間再執(zhí)行觀察):
jcmd pid VM.native_memory scale=MB summary.diff

3.堆外內(nèi)存檢查

通過(guò)pmap打印內(nèi)存的分布情況,并從打到小排序

pmap 2730 -x | sort -k 3 -n -r > /tmp/pmap20230131

打印jcmd內(nèi)存使用明細(xì)

jcmd 2730 VM.native_memory detail scale=MB > /tmp/jcmd20230131.txt

在pmap文件中,發(fā)現(xiàn)大量的64M的地址;而這些地址空間不在jcmd命令所給出的地址空間里面(例如通過(guò)pmap其中一個(gè)內(nèi)存地址7f6f90000000,去jcmd明細(xì)中搜索,無(wú)法搜到即為沒有在jvm中有引用),基本上就斷定就是這些64M的內(nèi)存所導(dǎo)致。

4.排查堆外內(nèi)存

因猜測(cè)是Native Code所引起,Java層面的工具不便于排查此類問(wèn)題,只能使用系統(tǒng)層面的工具去定位問(wèn)題。

1.使用smaps查看內(nèi)存的起始地址

cat /proc/2730/smaps > /tmp/smaps20230131.txt

以上述7f6f90000000地址為例,因在jcmd中無(wú)法找到7f6f90000000地址的內(nèi)容,說(shuō)明非jvm內(nèi)存,在smaps文件中搜索7f6f90000000的起始地址。

2.使用gdb調(diào)試工具打印上述懷疑的內(nèi)存地址里面存儲(chǔ)的內(nèi)容(注:gdb從進(jìn)入到退出的中間時(shí)刻,會(huì)使java進(jìn)程無(wú)法訪問(wèn),處于掛起狀態(tài),生產(chǎn)環(huán)境小心使用)。

#進(jìn)入gdb
gdb -pid 2730
#打印內(nèi)存地址地址內(nèi)容(0x00007f6f90000000 0x00007f6f93fff000)為開始地址和結(jié)束地址
dump memory mem.bin 0x00007f6f90000000 0x00007f6f93fff000
#退出
quit
#將文本以字符串輸出
strings mem.bin > /tmp/mem20230131.txt

因進(jìn)入gdb會(huì)導(dǎo)致進(jìn)程無(wú)法訪問(wèn),建議使用下面的方式執(zhí)行命令

#0x00007f6f90000000 可以寫成0x7f6f90000000 
gdb --batch --pid 2730-ex "dump memory /tmp/ipo02061143.bin 0x7f6f90000000 0x7f6f93fff000"

可以看看里面有一些報(bào)錯(cuò)和具體的調(diào)用方法等,根據(jù)內(nèi)存里面的內(nèi)容進(jìn)行逐一檢查即可

5.glibc內(nèi)存泄露

像上述的問(wèn)題,內(nèi)存內(nèi)容里面沒有可疑點(diǎn),并且pmap打印的內(nèi)容中有大量的64M內(nèi)存區(qū)域,由此可發(fā)現(xiàn),這是linux經(jīng)典的glibc內(nèi)存泄露問(wèn)題,后續(xù)會(huì)專門寫一篇文章介紹linux內(nèi)存管理以及glibc相關(guān)的原理,這里先直接說(shuō)明結(jié)論。

原因:

glibc 的內(nèi)存分配策略導(dǎo)致的碎片化內(nèi)存回收問(wèn)題,導(dǎo)致看起來(lái)像是內(nèi)存泄露,那有沒有更好一點(diǎn)的對(duì)碎片化內(nèi)存的 malloc 庫(kù)呢?業(yè)界常見的有 google 家的 tcmalloc 和 facebook 家的 jemalloc。

tcmalloc

#安裝
yum install gperftools-libs.x86_64 
#使用 LD_PRELOAD 掛載
export LD_PRELOAD="/usr/lib64/libtcmalloc.so.4.4.5"

注意 java 應(yīng)用要重啟

jemalloc

#安裝
yum install epel-release  -y
yum install jemalloc -y
#使用 LD_PRELOAD 掛載
export LD_PRELOAD="/usr/lib64/libjemalloc.so.1"

使用 jemalloc 后,RSS 內(nèi)存呈周期性波動(dòng),波動(dòng)范圍約 2 個(gè)百分點(diǎn)以內(nèi),基本控制住了

總結(jié)

到此這篇關(guān)于jvm堆外內(nèi)存排查的文章就介紹到這了,更多相關(guān)jvm堆外內(nèi)存排查內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java多線程并發(fā)編程和鎖原理解析

    Java多線程并發(fā)編程和鎖原理解析

    這篇文章主要介紹了Java多線程并發(fā)編程和鎖原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Java中常見的4種限流算法詳解

    Java中常見的4種限流算法詳解

    這篇文章主要介紹了Java中常見的4種限流算法詳解,FixedWindowRateLimiter 類表示一個(gè)固定窗口限流器,使用 limit 和 interval 參數(shù)分別表示限制請(qǐng)求數(shù)量和時(shí)間間隔,缺點(diǎn)是短時(shí)間內(nèi)可能會(huì)流量翻倍,需要的朋友可以參考下
    2023-12-12
  • Java線程并發(fā)訪問(wèn)代碼分析

    Java線程并發(fā)訪問(wèn)代碼分析

    這篇文章主要介紹了Java線程并發(fā)訪問(wèn)代碼分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • idea SpringBoot+Gradle環(huán)境配置到項(xiàng)目打包

    idea SpringBoot+Gradle環(huán)境配置到項(xiàng)目打包

    Gradle是一個(gè)基于Java應(yīng)用的項(xiàng)目自動(dòng)化構(gòu)建工具,本文介紹了在IDEA中創(chuàng)建Spring Boot Gradle項(xiàng)目,項(xiàng)目配置包括init.gradle和settings.gradle,感興趣的可以了解一下
    2024-11-11
  • 教你怎么用Java開發(fā)掃雷游戲

    教你怎么用Java開發(fā)掃雷游戲

    我們那時(shí)候上機(jī)經(jīng)常玩掃雷,試想如果我當(dāng)年可以用 java 寫個(gè)掃雷出來(lái),那場(chǎng)面不用我多說(shuō)了吧,大家讓開,我要開始裝逼了,之前用JavaScript寫過(guò)了一個(gè)掃雷,這次我用java再寫了一遍,權(quán)當(dāng)是復(fù)習(xí)咯.文中有非常詳細(xì)的代碼示例,需要的朋友可以參考下
    2021-05-05
  • Java設(shè)計(jì)模式中觀察者模式詳解

    Java設(shè)計(jì)模式中觀察者模式詳解

    觀察者模式是極其重要的一個(gè)設(shè)計(jì)模式,也是我?guī)啄觊_發(fā)過(guò)程中使用最多的設(shè)計(jì)模式,本文首先概述觀察者模式的基本概念和Demo實(shí)現(xiàn),接著是觀察者模式在Java和Spring中的應(yīng)用,最后是對(duì)觀察者模式的應(yīng)用場(chǎng)景和優(yōu)缺點(diǎn)進(jìn)行總結(jié)
    2022-11-11
  • Java集成swagger文檔組件

    Java集成swagger文檔組件

    這篇文章主要介紹了Java集成swagger文檔組件,通過(guò)詳細(xì)的圖文介紹和代碼分析展示,從頭展開說(shuō)明詳細(xì)的過(guò)程,希望對(duì)你的開發(fā)有所幫助
    2021-06-06
  • Spring Data Redis 中的 opsFor 方法深入解析

    Spring Data Redis 中的 opsFor 方法深入解析

    opsFor是RedisTemplate類中的一系列方法,用于獲取特定數(shù)據(jù)類型的操作接口,這些方法返回的是 Operations 對(duì)象,每個(gè)對(duì)象都提供了針對(duì)特定 Redis 數(shù)據(jù)類型的操作方法,本文重點(diǎn)介紹Spring Data Redis 中的opsFor方法,感興趣的朋友一起看看吧
    2025-12-12
  • 為IntelliJ IDEA配置JVM參數(shù)的兩種方法

    為IntelliJ IDEA配置JVM參數(shù)的兩種方法

    在使用IntelliJ IDEA進(jìn)行Java開發(fā)時(shí),合理配置JVM參數(shù)對(duì)于優(yōu)化項(xiàng)目性能和資源管理至關(guān)重要,IntelliJ IDEA提供了兩種方便的方式來(lái)設(shè)置JVM參數(shù),本文將詳細(xì)介紹這兩種方法:通過(guò)工具欄編輯配置和通過(guò)服務(wù)編輯配置,需要的朋友可以參考下
    2024-12-12
  • Java算法真題詳解運(yùn)用單調(diào)棧

    Java算法真題詳解運(yùn)用單調(diào)棧

    一般使用單調(diào)棧無(wú)非兩個(gè)方向,單調(diào)遞減,單調(diào)遞增。單調(diào)遞增棧:存進(jìn)去的數(shù)據(jù)都是增加的,碰到減少的時(shí)候,這時(shí)就要進(jìn)行操作了。單調(diào)遞減棧:存進(jìn)去的數(shù)據(jù)都是減少的,碰到增加的時(shí)候,這時(shí)就要進(jìn)行操作了,下面我們?cè)谡骖}中運(yùn)用它
    2022-07-07

最新評(píng)論

双桥区| 宜阳县| 汉中市| 印江| 江达县| 新田县| 井冈山市| 麻阳| 锡林郭勒盟| 河津市| 伊金霍洛旗| 皋兰县| 临邑县| 晋江市| 威远县| 腾冲县| 浮山县| 芜湖县| 鱼台县| 盐源县| 湘乡市| 分宜县| 永和县| 和政县| 嘉峪关市| 邢台县| 曲沃县| 中江县| 梅河口市| 洞头县| 合水县| 且末县| 泰和县| 旬阳县| 宜阳县| 陇川县| 安阳市| 西宁市| 曲沃县| 册亨县| 阳曲县|