成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java應用中本地內存(native memory)泄漏排查方法及如何預防?

開發 前端
本地內存跟蹤(NMT)是Java虛擬機(JVM)提供的一項功能,允許開發者監控和分析Java應用程序中本地內存的分配和使用情況。它有助于識別和診斷本地內存泄漏和過度內存消耗。

最近在開發的時候,遇到了內存泄漏問題。排查的過程中也是走了一遍Java內存泄漏的排查步驟。補充一點,Java 在heap dump的時候,是不會把native memory給dump出來的。因此如果你的程序是native memory leak,那使用jmap等工具進行heap dump拿到堆轉儲文件時,是分析不出來什么有價值的東西的。 比如程序RSS內存占用20GB,但是heap dump下來只有2GB。

那本文就想總結一下native memory內存泄漏的排查。

主要有以下幾部分知識點:

  1. NMT(本地內存追蹤);
  2. pmap + gdb找到對應內存地址的內容;
  3. 如何避免native memory內存泄漏;

一、NMT(本地內存追蹤,native memory tracking)

本地內存跟蹤(NMT)是Java虛擬機(JVM)提供的一項功能,允許開發者監控和分析Java應用程序中本地內存的分配和使用情況。它有助于識別和診斷本地內存泄漏和過度內存消耗。

下面詳細說下開啟NMT追蹤內存的步驟:

1.1 開啟NMT開關

在Java程序的JVM參數里加下面的參數:

-XX:NativeMemoryTracking=detail

具體加的方式有:

1.1.1 使用命令行的方式

java -XX:NativeMemoryTracking=detail -jar YourApp.jar

1.1.2 使用maven或者gradle構建工具

如果你使用像Maven或Gradle這樣的構建工具,你可以在構建配置文件中配置JVM選項。例如,在Maven的pom.xml文件中,你可以添加以下配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <argLine>-XX:NativeMemoryTracking=detail</argLine>
            </configuration>
        </plugin>
    </plugins>
</build>

1.2 為NMT定義baseline

我們先用下面的命令定義一個baseline,這樣后面再執行命令的時候,能跟這個baseline作對比。 可以更清楚的看到,內存增長了多少。

jcmd <PID> VM.native_memory baseline scale=MB

1.3 捕捉內存details

使用如下命令,將得到native memory的快照,輸出到native_memory_detail文件里。

jcmd <PID> VM.native_memory detail scale=MB > native_memory_detail

native_memory_detail文件的內容類似如下:

圖片圖片

reserved — 系統為此進程保留的內存 committed — 當前使用的數量

1.4 捕捉內存diff

然后我們可以定期捕獲native memory diff,以檢查隨時間推移committed 內存增加的組件。我們可以使用以下命令。

jcmd <PID> VM.native_memory detail.diff scale=MB > native_memory_diff

仔細看,這個命令里用的是detail.diff。 使用這個diff版本的命令之后,我們會得到類似如下的輸出。 可以看到,在reserved 、committed值后面都有 + 號,是與baseline做對比得到的。

圖片圖片

其中Total: reserved=3111MB +521MB, committed=1401MB +842MB的意思是, reserved總計3111MB,比baseline多了521MB,committed同理。

+521MB表示的是變化量。

當我們根據diff信息發現是哪些地方導致的內存增長之后,可以使用jcmd <PID> help命令查看更多的選項,然后針對性的track。 例如跟Class相關的。

jcmd <PID> VM.classloader_stats
jcmd <PID> VM.class_hierarchy

圖片圖片

二、pmap命令 + gdb分析dump

使用 pmap -x [PID] 命令查看java程序的內存使用。我們會看到類似如下的輸出:

Address           Kbytes     RSS   Dirty Mode  Mapping
0000000000400000       4       4       0 r-xp  /usr/bin/pmap
0000000000600000       4       4       4 rw-p  /usr/bin/pmap
...
00007f8b00000000   65512   40148   40148 rwx--    [ anon ]
00007f8b03ffa000      24       0       0 -----    [ anon ]
00007f8b04000000   65520   59816   59816 rwx--    [ anon ]
00007f8b07ffc000      16       0       0 -----    [ anon ]

從左到右的列,依次是:

  1. Address: 內存區域的起始地址
  2. Kbytes: 內存區域大小(KB)
  3. RSS: 實際使用的物理內存(KB)
  4. Dirty: 臟頁數量
  5. Mode: 內存權限(r=讀, w=寫, x=執行, s=共享, p=私有)
  6. Mapping: 內存映射類型或文件名

我們接下來使用gdb來dump地址00007f8b00000000開始的內存:

gdb -pid [pid]


dump memory mem.bin 0x00007f8b00000000 0x00007f8b00000000+65512

接著將二進制解析提取可讀字符串:

cat mem.bin | strings

三、如何避免native memory內存泄漏

3.1 正確管理Direct Memory:及時釋放ByteBuffer。

public class DirectMemoryManager {
    private static final long MAX_DIRECT_MEMORY = 1024 * 1024 * 1024; // 1GB
    private static final AtomicLong usedDirectMemory = new AtomicLong(0);


    public static ByteBuffer allocateDirect(int size) {
        long current = usedDirectMemory.get();
        if (current + size > MAX_DIRECT_MEMORY) {
            throw new OutOfMemoryError("Direct memory limit exceeded");
        }


        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        usedDirectMemory.addAndGet(size);


        return buffer;
    }


    public static void releaseDirect(ByteBuffer buffer) {
        if (buffer.isDirect()) {
            usedDirectMemory.addAndGet(-buffer.capacity());
            buffer.clear();
        }
    }
}

3.2 使用資源池:避免頻繁分配/釋放

public class DirectBufferPool {
    private final Queue<ByteBuffer> pool = new ConcurrentLinkedQueue<>();
    private final int bufferSize;
    private final int maxPoolSize;


    public DirectBufferPool(int bufferSize, int maxPoolSize) {
        this.bufferSize = bufferSize;
        this.maxPoolSize = maxPoolSize;
    }


    public ByteBuffer acquire() {
        ByteBuffer buffer = pool.poll();
        if (buffer == null) {
            buffer = ByteBuffer.allocateDirect(bufferSize);
        }
        return buffer;
    }


    public void release(ByteBuffer buffer) {
        if (buffer != null && buffer.isDirect() && pool.size() < maxPoolSize) {
            buffer.clear();
            pool.offer(buffer);
        }
    }
}

3.3 啟用NMT監控:及時發現內存增長(會有性能損耗)

3.4 定期清理:使用GC和自定義清理機制

public class NativeMemoryCleaner {
    private static final ScheduledExecutorService scheduler = 
        Executors.newScheduledThreadPool(1);


    public static void startPeriodicCleanup() {
        scheduler.scheduleAtFixedRate(() -> {
            System.gc(); // 觸發GC,釋放Direct Memory


            // 強制清理DirectByteBuffer
            try {
                Field cleanerField = Class.forName("java.nio.DirectByteBuffer")
                    .getDeclaredField("cleaner");
                cleanerField.setAccessible(true);


                // 這里可以添加自定義清理邏輯
            } catch (Exception e) {
                // 處理異常
            }
        }, 0, 5, TimeUnit.MINUTES);
    }
}

3.5 合理配置JVM參數:限制內存使用

# 限制Direct Memory大小
-XX:MaxDirectMemorySize=1g
# 啟用詳細GC日志
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps
# 啟用NMT
-XX:NativeMemoryTracking=detail
# 設置合理的線程棧大小
-Xss256k


責任編輯:武曉燕 來源: 大數據技術部落
相關推薦

2019-02-20 09:29:44

Java內存郵件

2010-09-25 11:07:45

Java內存泄漏

2018-12-07 10:52:08

內存泄漏方法

2021-12-27 09:33:12

內存泄漏程序

2022-12-13 10:59:47

devtoolMemory

2025-03-03 05:20:00

2014-07-30 14:22:41

AndroidWebView內存泄漏

2017-12-21 18:41:46

Java內存泄漏代碼

2025-02-28 06:23:38

2024-01-30 10:12:00

Java內存泄漏

2024-07-03 11:28:15

2025-04-02 08:17:42

2022-06-15 16:04:13

Java編程語言

2022-05-26 09:51:50

JavaScrip內存泄漏

2021-11-05 08:28:27

內存泄漏調試

2021-06-28 08:00:00

Python開發編程語言

2017-11-09 16:07:00

Web應用內存

2016-08-22 08:36:14

ReactiveCoc內存泄漏GitHub

2023-12-18 10:45:23

內存泄漏計算機服務器

2022-05-13 23:46:52

GO編程內存
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 激情福利视频 | 涩爱av一区二区三区 | 亚洲成人一区二区在线 | 亚洲精品在线91 | 日韩精品久久一区二区三区 | 国产亚洲精品久久19p | 国产日韩在线观看一区 | 精品九九在线 | 黑人精品欧美一区二区蜜桃 | 国产精品久久久久久久久久 | avav在线看| 欧美一区二区三区四区在线 | 国产精品一区二区无线 | 国产一区二区 | 日韩一二三区 | 国产精品视频一区二区三区, | 中文字幕色站 | 久久久久久黄 | 91极品尤物在线播放国产 | 99国内精品久久久久久久 | 日韩色视频| 欧美激情综合 | 欧美日日日日bbbbb视频 | 成人精品毛片 | 国产黄色免费网站 | 国产97碰免费视频 | 欧美一区二区三区在线看 | 在线观看免费黄色片 | 亚洲精品视频导航 | av网站在线看 | 亚洲自拍一区在线观看 | 中文在线播放 | 日韩在线免费视频 | 国产在线视频一区 | 久久久男人的天堂 | 国产大片黄色 | 国产精品久久久久久久久久久久久 | av综合站| 在线日韩 | 在线视频三区 | 99精品久久|