jvm 性能分析值 visual vm 以及 jhat、mat使用

本文介绍如何使用VisualVM工具来检测远程服务的Java虚拟机状态,包括使用VisualVM的远程连接功能,以及通过jmap和jhat进行更深入的对象分析。详细步骤包括下载并选择合适的版本,配置远程连接,生成heap dump文件,并通过jhat进行可视化分析。

1. 使用 visual vm, 下载地址 http://visualvm.java.net/, visual vm 1.3.8 仅支持 jdk7 以上版本,jdk1.6,请下载 visual vm 1.3.6

2.  检测远程服务jvm 状况,  点击 remote ,点击添加host, 右键 add jmx connection,填入hostname或者ip,以及所开启的远程检测端口




3. 以上数据只是图形化的显示heap的状态,如果想知道heap的实际锁包含的对象,以及那部分对象所占内存空间大,使用 jmap、jhat 进行分析

jmap -dump:live,file=a.map pid ( 所需要监测进程pid)   === 生成 a.map 文件

jhat  a.map 



访问  :  http://服务器ip/7000,  如下图



4. 找到  heap histogram 数据,看看各个对象所包含的个数其所占用的大小


参考:

http://jiajun.iteye.com/blog/1180230

http://blog.youkuaiyun.com/gtuu0123/article/details/6039474

<think>我们将讨论如何测试Java程序的内存消耗。主要方法包括使用Java内置工具、命令行工具、可视化工具以及编程方式监控内存。 1. 使用Runtime类获取内存使用情况(简单,但精度有限) 2. 使用Java Management Extensions (JMX) 提供更详细的内存信息 3. 使用命令行工具如jstat 4. 使用可视化工具如JConsole, VisualVM, Java Mission Control 5. 使用Profiler工具(如YourKit, JProfiler)进行深度分析 下面我们分别给出代码示例和解释。</think>### 测试 Java 程序内存消耗的完整指南 测试 Java 程序的内存消耗是性能优化和内存泄漏检测的关键步骤。以下是多种方法的详细实现和解释: #### 1. 使用 Java 内置工具(Runtime 类) ```java public class MemoryMonitor { public static void main(String[] args) { // 获取运行时实例 Runtime runtime = Runtime.getRuntime(); // 打印内存信息 printMemoryStats("程序启动", runtime); // 模拟内存消耗 List<byte[]> memoryHog = new ArrayList<>(); for (int i = 0; i < 100; i++) { memoryHog.add(new byte[1024 * 1024]); // 分配1MB printMemoryStats("分配后 " + (i+1) + "MB", runtime); } // 清理内存 memoryHog.clear(); System.gc(); // 建议GC运行(不保证立即执行) printMemoryStats("清理后", runtime); } private static void printMemoryStats(String phase, Runtime runtime) { // 内存单位转换 (bytes to MB) long free = runtime.freeMemory() / (1024 * 1024); long total = runtime.totalMemory() / (1024 * 1024); long max = runtime.maxMemory() / (1024 * 1024); long used = total - free; System.out.printf("[%s] 已用: %d MB, 空闲: %d MB, 总量: %d MB, 最大: %d MB%n", phase, used, free, total, max); } } ``` **代码解释**: 1. `Runtime.getRuntime()` 获取 JVM 运行时实例 2. `freeMemory()` 返回可用内存量 3. `totalMemory()` 返回当前堆内存总量 4. `maxMemory()` 返回 JVM 可用的最大内存量 5. `System.gc()` 建议 JVM 运行垃圾回收(非强制) **输出示例**: ``` [程序启动] 已用: 2 MB, 空闲: 61 MB, 总量: 63 MB, 最大: 1820 MB [分配后 1MB] 已用: 3 MB, 空闲: 60 MB, 总量: 63 MB, 最大: 1820 MB ... [分配后 100MB] 已用: 102 MB, 空闲: 0 MB, 总量: 123 MB, 最大: 1820 MB [清理后] 已用: 2 MB, 空闲: 121 MB, 总量: 123 MB, 最大: 1820 MB ``` #### 2. 使用 Java Management Extensions (JMX) ```java import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryUsage; public class JMXMemoryMonitor { public static void main(String[] args) { MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); // 监控堆内存 monitorMemory("初始状态", memoryMXBean); // 创建内存负载 List<String> strings = new ArrayList<>(); for (int i = 0; i < 1_000_000; i++) { strings.add(new String("String-" + i)); if (i % 100000 == 0) { monitorMemory("添加 " + i + " 个字符串", memoryMXBean); } } // 模拟内存泄漏(保留引用) // strings.clear(); // 注释掉以模拟内存泄漏 System.gc(); monitorMemory("GC后", memoryMXBean); } private static void monitorMemory(String phase, MemoryMXBean memoryMXBean) { MemoryUsage heapUsage = memoryMXBean.getHeapMemoryUsage(); MemoryUsage nonHeapUsage = memoryMXBean.getNonHeapMemoryUsage(); System.out.println("===== " + phase + " ====="); printMemoryUsage("堆内存", heapUsage); printMemoryUsage("非堆内存", nonHeapUsage); System.out.println("已提交内存: " + (heapUsage.getCommitted() + nonHeapUsage.getCommitted()) / (1024 * 1024) + " MB"); System.out.println(); } private static void printMemoryUsage(String type, MemoryUsage usage) { System.out.println(type + ":"); System.out.println(" 初始: " + usage.getInit() / (1024 * 1024) + " MB"); System.out.println(" 已用: " + usage.getUsed() / (1024 * 1024) + " MB"); System.out.println(" 提交: " + usage.getCommitted() / (1024 * 1024) + " MB"); System.out.println(" 最大: " + (usage.getMax() == -1 ? "无限制" : usage.getMax() / (1024 * 1024) + " MB")); } } ``` **代码解释**: 1. `ManagementFactory.getMemoryMXBean()` 获取内存管理 Bean 2. `getHeapMemoryUsage()` 返回堆内存使用详情 3. `getNonHeapMemoryUsage()` 返回非堆内存(元空间、线程栈等)使用详情 4. `MemoryUsage` 提供更详细的内存统计(初始、已用、提交、最大) #### 3. 使用 VisualVM 进行可视化监控 1. **启动 VisualVM**: ```bash jvisualvm ``` 2. **连接目标进程**: - 左侧选择你的 Java 进程 - 安装 "Visual GC" 插件(工具 > 插件 > 可用插件) 3. **内存分析功能**: - **监视器**:实时内存/CPU使用 - **Visual GC**:堆内存分区可视化 - **抽样器**:内存分配热点分析 - **Profiler**:详细内存分配跟踪 #### 4. 使用 JConsole 监控 ```bash # 启动 JConsole jconsole ``` **主要功能**: - 内存选项卡:堆/非堆内存使用曲线 - 线程监控:线程状态和堆栈跟踪 - MBean 浏览器:查看所有管理 Bean - VM 摘要:JVM 配置概览 #### 5. 使用命令行工具 **jstat - 内存统计**: ```bash # 每1秒监控一次进程12345的内存使用 jstat -gcutil 12345 1000 ``` 输出列说明: - `S0`/`S1`:Survivor 区使用率 - `E`:Eden 区使用率 - `O`:老年代使用率 - `M`:元空间使用率 - `CCS`:压缩类空间使用率 - `YGC`/`YGCT`:Young GC 次数/时间 - `FGC`/`FGCT`:Full GC 次数/时间 **jmap - 堆转储分析**: ```bash # 生成堆转储 jmap -dump:live,format=b,file=heapdump.hprof 12345 # 分析堆转储(使用jhatVisualVMjhat heapdump.hprof ``` #### 6. 使用内存分析工具(MAT) 1. 下载 Eclipse Memory Analyzer:https://www.eclipse.org/mat/ 2. 加载堆转储文件(.hprof) 3. 关键功能: - **直方图**:按类分组的对象数量 - **支配树**:对象引用关系 - **泄漏嫌疑报告**:自动检测潜在泄漏 - **OQL**:类似SQL的对象查询 #### 7. 高级内存跟踪(Java Flight Recorder) ```bash # 启动记录 jcmd <PID> JFR.start name=memrec settings=profile # 转储记录 jcmd <PID> JFR.dump name=memrec filename=recording.jfr # 使用JDK Mission Control分析 jmc ``` **关键特性**: - 低开销的生产环境监控 - 内存分配热点 - GC暂停时间分析 - 对象分配统计 ### 内存测试最佳实践 1. **测试环境**: ```bash # 设置固定堆大小以便测试 java -Xms512m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError YourApp ``` 2. **内存泄漏检测模式**: - 创建基准内存快照 - 执行操作(如处理100个请求) - 强制GC后比较内存变化 - 分析未回收对象的引用链 3. **压力测试脚本**: ```java // 使用JMH进行基准测试 @Benchmark @BenchmarkMode(Mode.SingleShotTime) @Measurement(iterations = 10) public void testMemoryUsage() { // 测试代码 } ``` ### 常见内存问题诊断 | 问题现象 | 诊断工具 | 解决方案 | |---------|---------|---------| | 内存持续增长 | VisualVM + MAT | 分析对象保留路径 | | Full GC 频繁 | JFR + GC日志 | 调整堆大小/GC策略 | | 元空间溢出 | jstat -gcmetacapacity | 增加 -XX:MaxMetaspaceSize | | 直接内存泄漏 | NMT (Native Memory Tracking) | 检查 ByteBuffer 使用 | | 线程泄漏 | jstack | 分析线程堆栈 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值