SourceCode Java SpringBoot Linux Spring Code

Java内存占用超出Xmx原因

Posted on 2022-04-20,3 min read
  • 在Java中,我们常常使用-Xms-Xmn-Xmx来指定运行时的堆内存的占用。然而当我们通过top命令去查看当前程序内存占用情况的时候,经常会发现实际占用的内存远远的大于我们指定的内存。

  • 如以下程序:

    public class HelloWorld {
        public static void main(String[] args) throws Exception {
            System.out.println("Hello world!");
            Thread.sleep(10000);
        }
    }
    
  • 然后打印其内存占用:

    $ 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来查看具体的使用情况,得到的结果如下:

    $ 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)将会显示占用的所有内存。因此会出现大小不一致的情况。


下一篇: 无状态验证码工具类→

loading...