进程物理内存远大于Xmx的问题分析

本文探讨了Java进程中物理内存(Res/Rss)远超Xmx设置值的现象,解析了Xmx参数仅涵盖的部分内存区域,并非全部,从而解释了为何实际使用的物理内存可能会超出Xmx值。同时介绍了操作系统如何管理和映射物理内存与虚拟内存,以及通过实验工具分析了具体的内存使用情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

最近经常被问到一个问题,”为什么我们系统进程占用的物理内存(Res/Rss)会远远大于设置的Xmx值”,比如Xmx设置1.7G,但是top看到的Res的值却达到了3.0G,随着进程的运行,Res的值还在递增,直到达到某个值,被OS当做bad process直接被kill掉了。

1
2
3
4
5
6
7
top - 16:57:47 up 73 days,  4:12,  8 users,  load average: 6.78, 9.68, 13.31
Tasks: 130 total,   1 running, 123 sleeping,   6 stopped,   0 zombie
Cpu(s): 89.9%us,  5.6%sy,  0.0%ni,  2.0%id,  0.7%wa,  0.7%hi,  1.2%si,  0.0%st
  ...
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
22753 admin     20   0 4252m 3.0g  17m S 192.8 52.7 151:47.59 /opt/taobao/java/bin/java -server -Xms1700m -Xmx1700m -Xmn680m -Xss256k -XX:PermSize=128m -XX:MaxPermSize=128m -XX:+UseStringCache -XX:+
   40 root      20   0     0    0    0 D  0.3  0.0   5:53.07 [kswapd0]

物理内存大于Xmx可能吗

先说下Xmx,这个vm配置只包括我们熟悉的新生代和老生代的最大值,不包括持久代,也不包括CodeCache,还有我们常听说的堆外内存从名字上一看也知道没有包括在内,当然还有其他内存也不会算在内等,因此理论上我们看到物理内存大于Xmx也是可能的,不过超过太多估计就可能有问题了。

物理内存和虚拟内存间的映射关系

我们知道os在内存上面的设计是花了心思的,为了让资源得到最大合理利用,在物理内存之上搞一层虚拟地址,同一台机器上每个进程可访问的虚拟地址空间大小都是一样的,为了屏蔽掉复杂的到物理内存的映射,该工作os直接做了,当需要物理内存的时候,当前虚拟地址又没有映射到物理内存上的时候,就会发生缺页中断,由内核去为之准备一块物理内存,所以即使我们分配了一块1G的虚拟内存,物理内存上不一定有一块1G的空间与之对应,那到底这块虚拟内存块到底映射了多少物理内存呢,这个我们在linux下可以通过/proc/<pid>/smaps这个文件看到,其中的Size表示虚拟内存大小,而Rss表示的是物理内存,所以从这层意义上来说和虚拟内存块对应的物理内存块不应该超过此虚拟内存块的空间范围

1
2
3
4
5
6
7
8
9
10
11
12
13
14
8dc00000-100000000 rwxp 00000000 00:00 0
Size:            1871872 kB
Rss:             1798444 kB
Pss:             1798444 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:   1798444 kB
Referenced:      1798392 kB
Anonymous:       1798444 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB

此次为了排查这个问题,我特地写了个简单的分析工具来分析这个问题,将连续的虚拟内存块合并做统计,一般来说连续分配的内存块还是有一定关系的,当然也不能完全肯定这种关系,得到的效果大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from->to  vs rss rss_percentage(rss/total_rss) merge_block_count

0x8dc00000->0x30c9a20000      1871872      1487480      53.77%     1
0x7faf7a4c5000->0x7fffa7dd9000      1069464      735996      26.60%     440
0x7faf50c75000->0x7faf6c02a000      445996      226860      8.20%     418
0x7faf6c027000->0x7faf78010000      196452      140640      5.08%     492
0x418e8000->0x100000000      90968      90904      3.29%     1
0x7faf48000000->0x7faf50c78000      131072      35120      1.27%     4
0x7faf28000000->0x7faf3905e000      196608      20708      0.75%     6
0x7faf38000000->0x7faf4ad83000      196608      17036      0.62%     6
0x7faf78009000->0x7faf7a4c6000      37612      10440      0.38%     465
0x30c9e00000->0x30ca202000      3656      716      0.03%     5
0x7faf20000000->0x7faf289c7000      65536      132      0.00%     2
0x30c9a00000->0x30c9c20000      128      108      0.00%     1
0x30ca600000->0x30cae83000      2164      76      0.00%     5
0x30cbe00000->0x30cca16000      2152      68      0.00%     5
0x7fffa7dc3000->0x7fffa7e00000      92      48      0.00%     1
0x30cca00000->0x7faf21dba000      2148      32      0.00%     5
0x30cb200000->0x30cbe16000      2080      28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值