Jar文件未显示全部属性:获取运行中Jar堆内存信息失败
解决获取运行中Jar堆内存信息的问题
哦,我懂你碰到的麻烦了——用VirtualMachine.getAgentProperties()确实拿不到堆内存相关的数据,这完全是因为这个方法的定位就不是用来获取运行时内存指标的😉
为什么getAgentProperties()拿不到堆内存数据?
getAgentProperties()返回的是和JVM agent相关的系统属性集合,比如agent的启动参数、加载路径这类配置信息,和JVM运行时的内存使用情况根本不是一个范畴的东西,所以堆内存相关的属性自然会返回null。
正确获取堆内存信息的方法
要获取JVM的堆内存使用情况,你需要通过VirtualMachine拿到MBeanServer连接,然后借助JMX的MemoryMXBean来获取详细的内存指标。下面是具体的代码示例:
import com.sun.tools.attach.VirtualMachine; import javax.management.MBeanServerConnection; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryUsage; public class JarMemoryMonitor { public static void main(String[] args) throws Exception { // 替换成你的目标Jar进程ID String pid = "your-process-id"; VirtualMachine vm = VirtualMachine.attach(pid); // 获取MBeanServer连接,这是访问JVM运行时指标的关键 MBeanServerConnection conn = vm.getMBeanServerConnection(); // 通过代理获取MemoryMXBean实例 MemoryMXBean memoryBean = ManagementFactory.newPlatformMXBeanProxy( conn, ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class ); // 获取堆内存使用详情 MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage(); System.out.println("当前堆内存已用: " + (heapUsage.getUsed() / 1024 / 1024) + " MB"); System.out.println("当前堆内存已分配: " + (heapUsage.getCommitted() / 1024 / 1024) + " MB"); System.out.println("堆内存最大值: " + (heapUsage.getMax() / 1024 / 1024) + " MB"); // 如果需要非堆内存信息,也可以用下面的代码 MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage(); System.out.println("非堆内存已用: " + (nonHeapUsage.getUsed() / 1024 / 1024) + " MB"); vm.detach(); } }
额外扩展:获取更细分的内存池信息
如果你需要了解新生代、老年代这类具体内存池的使用情况,可以获取MemoryPoolMXBean的列表,示例代码如下:
import java.lang.management.MemoryPoolMXBean; import java.util.List; // ... 前面的代码不变 List<MemoryPoolMXBean> poolBeans = ManagementFactory.newPlatformMXBeanProxy( conn, ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE, List.class ); for (MemoryPoolMXBean poolBean : poolBeans) { MemoryUsage usage = poolBean.getUsage(); System.out.println("\n内存池名称: " + poolBean.getName()); System.out.println("已用内存: " + (usage.getUsed() / 1024 / 1024) + " MB"); System.out.println("已分配内存: " + (usage.getCommitted() / 1024 / 1024) + " MB"); }
注意事项
- 运行监控程序的用户需要和目标Jar进程拥有相同的权限,否则
VirtualMachine.attach()可能会抛出权限异常。 - 确保监控程序使用的JDK版本和目标Jar进程的JDK版本兼容,避免出现版本不匹配的问题。
内容的提问来源于stack exchange,提问作者josef
相关产品推荐
相关产品推荐

