使用Runtime类获取JVM运行时内存的三类技术疑问
JVM内存配置与运行分析
IDEA VM参数
-Xmx100m -Xms100m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags
测试代码
public static void main(String[] args) { Runtime rt = Runtime.getRuntime(); System.out.println(rt.maxMemory()); System.out.println(rt.totalMemory()); System.out.println(rt.freeMemory()); }
运行输出
-XX:InitialHeapSize=104857600 -XX:MaxHeapSize=104857600 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC objc[73147]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java (0x108b194c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x108c5e4e0). One of the two will be used. Which one is undefined. 100663296 100663296 98035184 Heap PSYoungGen total 29696K, used 3078K [0x00000007bdf00000, 0x00000007c0000000, 0x00000007c0000000) eden space 25600K, 12% used [0x00000007bdf00000,0x00000007be201b88,0x00000007bf800000) from space 4096K, 0% used [0x00000007bfc00000,0x00000007bfc00000,0x00000007c0000000) to space 4096K, 0% used [0x00000007bf800000,0x00000007bf800000,0x00000007bfc00000) ParOldGen total 68608K, used 0K [0x00000007b9c00000, 0x00000007bdf00000, 0x00000007bdf00000) object space 68608K, 0% used [0x00000007b9c00000,0x00000007b9c00000,0x00000007bdf00000) Metaspace used 3269K, capacity 4496K, committed 4864K, reserved 1056768K class space used 359K, capacity 388K, committed 512K, reserved 1048576K
技术问题解答
1. 为什么maxMemory输出值小于配置的100MB?各内存指标含义是什么?
100MB换算字节是104857600,但输出的maxMemory是100663296字节,差异来自JVM会预留一小部分堆内存用于内部管理(比如GC标记、内存结构维护),这部分不会开放给应用程序使用。
三个指标的具体含义:
maxMemory():应用程序能用到的最大堆内存,等于-Xmx配置的上限减去JVM内部预留的管理空间。totalMemory():JVM当前已分配的堆内存总量,启动时等于-Xms的初始值,运行中会根据需求动态调整,但不会超过maxMemory。freeMemory():当前堆内存中未被使用的空间,等于totalMemory减去已使用的堆内存。
2. 为什么输出里Metaspace看起来属于Heap区域?
这只是日志排版的问题,Metaspace完全不属于堆内存。它是JDK8及以后在本地内存(Native Memory)中开辟的区域,专门存储类元数据、常量池等信息,用来替代之前的永久代。日志把它放在Heap区块下方打印,只是格式习惯,实际和堆内存是完全独立的。
3. PSYoungGen与ParOldGen的总和不等于100MB配置,原因是什么?
计算两者总和:29696K + 68608K = 98304K(约96MB),确实小于100MB。原因有两点:
一是年轻代除了Eden和Survivor区,JVM会预留一部分内存作为GC分配担保空间,用于老年代内存不足时的临时周转;
二是-Xmx配置的是整个堆的总上限,包含年轻代、老年代,以及JVM为堆内存分配的内部管理结构空间,这些额外空间不会被统计到YoungGen和OldGen的total值里,所以两者总和会略小于配置的堆内存上限。
内容的提问来源于stack exchange,提问作者Jack Ma
相关产品推荐
相关产品推荐

