在Java中,我们常常使用
-Xms
、-Xmn
、-Xmx
来指定运行时的堆内存的占用。然而当我们通过top命令去查看当前程序内存占用情况的时候,经常会发现实际占用的内存远远的大于我们指定的内存。如以下程序:
1
2
3
4
5
6public class HelloWorld {
public static void main(String[] args) throws Exception {
System.out.println("Hello world!");
Thread.sleep(10000);
}
}然后打印其内存占用:
1
2
3
4
5
6
7$ nohup java -Xms2m -Xmx2m HelloWorld &
$ ps aux | awk 'NR==1; /[H]elloWorld/'
# 输出
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
chaospie 6204 6.0 0.1 2662860 23040 pts/2 Sl 19:15 0:00 java -Xms2m -Xmx2m HelloWorld会发现实际使用的内存远远比配置的2m要多。
要排查具体使用的情况,则需要使用Java提供的
NativeMemorytracking
来进行查看。(文档)并且使用jcmd 进程id VM.native_memory summary
来查看具体的使用情况,得到的结果如下: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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53$ nohup java -XX:NativeMemoryTracking=summary -Xms2M -Xmx2M HelloWorld &
$ ps aux | awk 'NR==1; /[H]elloWorld/'
# 输出
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
chaospie 6661 5.0 0.1 2662860 23104 pts/2 Sl 19:21 0:00 java -XX:NativeMemoryTracking=summary -Xms2M -Xmx2M HelloWorld
jcmd 23012 VM.native_memory summary
# 输出
Native Memory Tracking:
Total: reserved=1360145KB, committed=61177KB
- Java Heap (reserved=2048KB, committed=2048KB)
(mmap: reserved=2048KB, committed=2048KB)
- Class (reserved=1066093KB, committed=14189KB)
(classes #402)
(malloc=9325KB #146)
(mmap: reserved=1056768KB, committed=4864KB)
- Thread (reserved=20646KB, committed=20646KB)
(thread #21)
(stack: reserved=20560KB, committed=20560KB)
(malloc=62KB #110)
(arena=23KB #40)
- Code (reserved=249632KB, committed=2568KB)
(malloc=32KB #299)
(mmap: reserved=249600KB, committed=2536KB)
- GC (reserved=10467KB, committed=10467KB)
(malloc=10383KB #129)
(mmap: reserved=84KB, committed=84KB)
- Compiler (reserved=132KB, committed=132KB)
(malloc=1KB #21)
(arena=131KB #3)
- Internal (reserved=9453KB, committed=9453KB)
(malloc=9421KB #1402)
(mmap: reserved=32KB, committed=32KB)
- Symbol (reserved=1358KB, committed=1358KB)
(malloc=902KB #86)
(arena=456KB #1)
- Native Memory Tracking (reserved=143KB, committed=143KB)
(malloc=86KB #1363)
(tracking overhead=57KB)
- Arena Chunk (reserved=175KB, committed=175KB)
(malloc=175KB)得到了以上的结果,其中reserved是保留的空间,而committed是当前正在使用的空间。可以看到,除了Java Heap堆空间以外,还有其他占用的空间,这些空间则是导致实际使用内存超出堆空间的主要原因。关于其他项是说明,可以参考官方文档
所以结论是,-Xmx只针对于堆空间进行限制,而top(或ps)将会显示占用的所有内存。因此会出现大小不一致的情况。