Native Memory Tracking 与 RSS的差异问题

news2025/2/1 10:01:23

一 问题现象

前一段时间用nmt查看jvm进程的栈区占用的内存大小。测试代码如下

public class ThreadOOM {

    public static void main(String[] args) {
        int i = 1;
        while (i < 3000) {
            Thread thread = new TestThread();
            thread.start();
            System.out.println("thread : " + i);
            i++;
        }
    }
}


class TestThread extends Thread {
    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(Long.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

启动命令

nohup java -Xms2G -Xmx2G -XX:MaxMetaspaceSize=512M -XX:NativeMemoryTracking=detail ThreadOOM &

用native memory tracking查看内存占用

jcmd 37898 VM.native_memory scale=MB
37898:

Native Memory Tracking:

Total: reserved=9366MB, committed=8211MB
-                 Java Heap (reserved=2048MB, committed=2048MB)
                            (mmap: reserved=2048MB, committed=2048MB)

-                     Class (reserved=1039MB, committed=12MB)
                            (classes #433)
                            (malloc=7MB #3218)
                            (mmap: reserved=1032MB, committed=5MB)

-                    Thread (reserved=6046MB, committed=6046MB)
                            (thread #3017)
                            (stack: reserved=6032MB, committed=6032MB)
                            (malloc=10MB #18096)
                            (arena=3MB #6029)

-                      Code (reserved=130MB, committed=3MB)
                            (mmap: reserved=130MB, committed=2MB)

-                        GC (reserved=83MB, committed=83MB)
                            (malloc=8MB #123)
                            (mmap: reserved=75MB, committed=75MB)

-                  Internal (reserved=17MB, committed=17MB)
                            (malloc=17MB #34406)

-                    Symbol (reserved=1MB, committed=1MB)
                            (malloc=1MB #110)

-    Native Memory Tracking (reserved=1MB, committed=1MB)
                            (tracking overhead=1MB)
                            

显示线程占用了6G左右,jvm总共committed了8G左右。
使用top查看,常驻物理内存(RES)才占用了139M,这个和nmt显示的差距太大了吧!commited内存不就应该是RES的大小吗?
在这里插入图片描述

二 jdk8申请内存的源码分析

我看的jdk的源码:https://github.com/openjdk/jdk
分支: jdk8-b120
文件位置: hotspot/src/os/linux/vm/os_linux.cpp

reserve内存

char* os::reserve_memory(size_t bytes, char* requested_addr,
                         size_t alignment_hint) {
  return anon_mmap(requested_addr, bytes, (requested_addr != NULL));
}

static char* anon_mmap(char* requested_addr, size_t bytes, bool fixed) {
  char * addr;
  int flags;

  flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS;
  if (fixed) {
    assert((uintptr_t)requested_addr % os::Linux::page_size() == 0, "unaligned address");
    flags |= MAP_FIXED;
  }

  // Map uncommitted pages PROT_READ and PROT_WRITE, change access
  // to PROT_EXEC if executable when we commit the page.
  addr = (char*)::mmap(requested_addr, bytes, PROT_READ|PROT_WRITE,
                       flags, -1, 0);

  if (addr != MAP_FAILED) {
    if ((address)addr + bytes > _highest_vm_reserved_address) {
      _highest_vm_reserved_address = (address)addr + bytes;
    }
  }

  return addr == MAP_FAILED ? NULL : addr;
}

commit内存

// NOTE: Linux kernel does not really reserve the pages for us.
//       All it does is to check if there are enough free pages
//       left at the time of mmap(). This could be a potential
//       problem.
bool os::commit_memory(char* addr, size_t size, bool exec) {
  int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
  uintptr_t res = (uintptr_t) ::mmap(addr, size, prot,
                                   MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
  return res != (uintptr_t) MAP_FAILED;
}

不管是reserve还是commit内存,背后都是调用mmap函数

三 mmap函数分析

函数原型

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

mmap主要做文件映射,也可以用来为进程申请内存。jdk显然是用来申请内存空间。但是这个系统函数调用后,os并不会立刻分配物理内存,而是等对申请到的内存块进行具体的读写之后再进行物理内存page实际分配。

测试代码

#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int test = 0;
    size_t initial_size = 1024*1024*50;  // 初始大小为 50MB
    size_t expanded_size = 1024*1024*512; // 扩展大小为 512MB

    // 创建映射区域
    void *ptr = mmap(NULL, initial_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
    if (ptr == MAP_FAILED) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }

    printf("Initial size: %zuKB\n", initial_size / 1024);
    scanf("%d", &test);

    // 使用 mremap 扩展映射区域的大小
    void *new_ptr = mremap(ptr, initial_size, expanded_size, MREMAP_MAYMOVE);
    if (new_ptr == MAP_FAILED) {
        perror("mremap");
        exit(EXIT_FAILURE);
    }

    printf("Expanded size: %zuKB\n", expanded_size / 1024);

    scanf("%d", &test);
    
    // 使用新的映射区域进行读写操作...

    //使用10M
    memset(new_ptr, 0, 1024 * 1024 * 10);
    scanf("%d", &test);
    
    // 使用100M
    memset(new_ptr, 0, 1024 * 1024 * 100);
    scanf("%d", &test);

    // 解除映射
    if (munmap(new_ptr, expanded_size) == -1) {
        perror("munmap");
        exit(EXIT_FAILURE);
    }

    return 0;
}

3.1 执行mmap函数

mmap函数执行后,查看top输出,虚拟内存52M接近申请的50M,而RES仅有1M
在这里插入图片描述

3.2 执行mremap

mremap执行后,查看top输出,虚拟内存涨到了514MB,接近扩容申请的512MB,RES常驻内存不变
在这里插入图片描述

3.3 执行第一个memset

接着执行第一个memset,进行内存写入。这次发现虚拟内存不变,而RES物理内存增长了10MB,这和memset的内存大小一致
在这里插入图片描述

3.4 执行第2个memset

接着执行第二个memset,写入100MB(指针位置没有变化)。虚存没有变化,RES增加了90MB。
在这里插入图片描述
使用pmp命令分析

lvsheng@lvsheng:/proc/36287$ pmap -x  41422
41422:   ./mmap
Address           Kbytes     RSS   Dirty Mode  Mapping
0000c8e2d33a0000       4       4       0 r-x-- mmap
0000c8e2d33bf000       4       4       4 r---- mmap
0000c8e2d33c0000       4       4       4 rw--- mmap
0000c8e309014000     132       4       4 rw---   [ anon ]
0000e16bc8c00000  524288  102400  102400 rw---   [ anon ]
0000e16bebe20000    1640    1088       0 r-x-- libc.so.6
0000e16bebfba000      76       0       0 ----- libc.so.6
0000e16bebfcd000      12      12      12 r---- libc.so.6
0000e16bebfd0000       8       8       8 rw--- libc.so.6
0000e16bebfd2000      48      16      16 rw---   [ anon ]
0000e16bebfdf000     156     156       0 r-x-- ld-linux-aarch64.so.1
0000e16bec018000       8       8       8 rw---   [ anon ]
0000e16bec01a000       8       0       0 r----   [ anon ]
0000e16bec01c000       4       4       0 r-x--   [ anon ]
0000e16bec01d000       8       8       8 r---- ld-linux-aarch64.so.1
0000e16bec01f000       8       8       8 rw--- ld-linux-aarch64.so.1
0000fffff236c000     132      12      12 rw---   [ stack ]
---------------- ------- ------- -------
total kB          526540  103736  102484

512MB的虚拟内存,OS分配了100MB物理内存

四 总结

在这里插入图片描述

  1. jdk通过mmap申请内存后,操作系统分配的虚拟内存,并没有分配实际的物理内存。
  2. 当Java应用程序实际写入时,OS才会分配物理内存。

所以nmt和top的RES指标的差异会很明显

参考文章


  1. https://blog.csdn.net/qq_41687938/article/details/119901916

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2289256.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

知识库管理如何推动企业数字化转型与创新发展的深层次探索

内容概要 在当今数字化转型的大背景下&#xff0c;知识库管理日益显现出其作为企业创新发展的核心驱动力的潜力。这种管理方式不仅仅是对信息的存储与检索&#xff0c;更是一种赋能&#xff0c;以提升决策效率和员工创造力。企业能够通过系统地整合和管理各类知识资源&#xf…

《DeepSeek 网页/API 性能异常(DeepSeek Web/API Degraded Performance):网络安全日志》

DeepSeek 网页/API 性能异常&#xff08;DeepSeek Web/API Degraded Performance&#xff09;订阅 已识别 - 已识别问题&#xff0c;并且正在实施修复。 1月 29&#xff0c; 2025 - 20&#xff1a;57 CST 更新 - 我们将继续监控任何其他问题。 1月 28&#xff0c; 2025 - 22&am…

DeepSeek-R1本地部署笔记

文章目录 效果概要下载 ollama终端下载模型【可选】浏览器插件 UIQ: 内存占用高&#xff0c;显存占用不高&#xff0c;正常吗 效果 我的配置如下 E5 2666 V3 AMD 590Gme 可以说是慢的一批了&#xff0c;内存和显卡都太垃圾了&#xff0c;回去用我的新设备再试试 概要 安装…

C++中常用的十大排序方法之1——冒泡排序

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C中常用的排序方法之——冒泡排序的相关…

数据结构实战之线性表(一)

一.线性表的定义和特点 线性表的定义 线性表是一种数据结构&#xff0c;它包含了一系列具有相同特性的数据元素&#xff0c;数据元素之间存在着顺序关系。例如&#xff0c;26个英文字母的字符表 ( (A, B, C, ....., Z) ) 就是一个线性表&#xff0c;其中每个字母就是一个数据…

Spring Boot项目如何使用MyBatis实现分页查询及其相关原理

写在前面&#xff1a;大家好&#xff01;我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正&#xff0c;感谢大家的不吝赐教。我的唯一博客更新地址是&#xff1a;https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油&#xff0c;冲鸭&#x…

【项目初始化】

项目初始化 使用脚手架创建项目Vite创建项目推荐拓展 使用脚手架创建项目 Vite Vite 是一个现代的前端构建工具&#xff0c;它提供了极速的更新和开发体验&#xff0c;支持多种前端框架&#xff0c;如 Vue、React 等创建项目 pnpm create vuelatest推荐拓展

LeetCode热题100(八)—— 438.找到字符串中所有字母异位词

LeetCode热题100&#xff08;八&#xff09;—— 438.找到字符串中所有字母异位词 题目描述代码实现思路解析 你好&#xff0c;我是杨十一&#xff0c;一名热爱健身的程序员在Coding的征程中&#xff0c;不断探索与成长LeetCode热题100——刷题记录&#xff08;不定期更新&…

26.Word:创新产品展示说明会【9】

目录 NO1.2.3​ NO4.5.6.7 NO1.2.3 另存为/F12&#xff1a;考生文件夹点亮显示和隐藏标记选中→插入→表格→文字转化成表格→✔制表符→确定布局→自动调整→设计→随便一种保存至“表格”部件库&#xff1a;选中表格→插入→文档部件→使用“表格”部件库&#xff1a;插入→…

反向代理模块jmh

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当…

全国31省空间权重矩阵(地理相邻空间、公路铁路地理距离空间、经济空间)权重矩阵数据-社科数据

中国31个省份空间权重矩阵-社科数据https://download.csdn.net/download/paofuluolijiang/90028597 https://download.csdn.net/download/paofuluolijiang/90028597 空间权重矩阵是反映个体在空间中依赖关系的矩阵&#xff0c;本数据计算全国31个省三种标准化处理的空间权重矩…

前端开发之jsencrypt加密解密的使用方法和使用示例

目录 RSA密钥生成选项简介 jsencrypt 使用教程 一、安装 jsencrypt 二、使用 jsencrypt 进行加密和解密 1. 创建密钥对 2. 加密数据 3. 解密数据 三、实际应用示例 加密数据并存储到 localStorage 中&#xff1a; 从 localStorage 中读取加密数据并解密&#xff1a; …

98.1 AI量化开发:长文本AI金融智能体(Qwen-Long)对金融研报大批量处理与智能分析的实战应用

目录 0. 承前1. 简介1.1 通义千问(Qwen-Long)的长文本处理能力 2. 基础功能实现2.1 文件上传2.2 单文件分析2.3 多文件分析 3. 汇总代码&运行3.1 封装的工具函数3.2 主要功能特点3.3 使用示例3.4 首次运行3.5 运行结果展示 4. 注意事项4.1 文件要求4.2 错误处理机制4.3 最佳…

PPT演示设置:插入音频同步切换播放时长计算

PPT中插入音频&同步切换&放时长计算 一、 插入音频及音频设置二、设置页面切换和音频同步三、播放时长计算 一、 插入音频及音频设置 1.插入音频&#xff1a;点击菜单栏插入-音频-选择PC上的音频&#xff08;已存在的音频&#xff09;或者录制音频&#xff08;现场录制…

链表的简单介绍

申明&#xff1a; 我们的链表可以写在类中或者接口中&#xff08;接口中更好&#xff09;&#xff0c;这里我们是写在类当中。 1.节点的构造是由当前数据和指向下一个结点的地址组成&#xff0c;那么我们在当前这个链表的类中需要实现一个节点那么此时就需要用到内部类(当一个…

基于聚类与相关性分析对马来西亚房价数据进行分析

碎碎念&#xff1a;由于最近太忙了&#xff0c;更新的比较慢&#xff0c;提前祝大家新春快乐&#xff0c;万事如意&#xff01;本数据集的下载地址&#xff0c;读者可以自行下载。 1.项目背景 本项目旨在对马来西亚房地产市场进行初步的数据分析&#xff0c;探索各州的房产市…

ARM嵌入式学习--第十一天(中断处理 , ADC)

--中断的概念 中断是指计算机运行过程中&#xff0c;出现某些意外情况需主机干预时&#xff0c;机器能自动停止正在运行的程序并转入处理新情况的程序&#xff0c;处理完毕后又返回被暂停的程序继续运行 --CPU处理事情的方式 -轮询方式 不断查询是否有事情需要处理&#xff0c…

消息队列篇--通信协议篇--网络通信模型(OSI7层参考模型,TCP/IP分层模型)

一、OSI参考模型&#xff08;Open Systems Interconnection Model&#xff09; OSI参考模型是一个用于描述和标准化网络通信功能的七层框架。它由国际标准化组织&#xff08;ISO&#xff09;提出&#xff0c;旨在为不同的网络设备和协议提供一个通用的语言和结构&#xff0c;以…

“新月之智”智能战术头盔系统(CITHS)

新月人物传记&#xff1a;人物传记之新月篇-CSDN博客 相关文章链接&#xff08;更新&#xff09;&#xff1a; 星际战争模拟系统&#xff1a;新月的编程之道-CSDN博客 新月智能护甲系统CMIA--未来战场的守护者-CSDN博客 目录 一、引言 二、智能头盔控制系统概述 三、系统架…

实验七 JSP内置对象II

实验七 JSP内置对象II 目的&#xff1a; 1、掌握JSP内置对象的使用。 2、理解JSP的作用域 3、掌握session&#xff0c;application对象的使用 实验要求&#xff1a; 1、完成实验题目 2、要求提交实验报告&#xff0c;将代码和实验结果页面截图放入报告中 实验过程&#xff1a…