JVM性能调优监控工具hprof使用详解

本文探讨了Java开发中常见的内存问题,如OutOfMemoryError和内存泄漏,并介绍了如何使用hprof工具进行JVM性能调优监控。通过生成hprof文件定位内存泄漏原因,并展示了如何在Tomcat中设置JVM参数。

一、问题现状

     现实企业级Java开发中,有时候我们会碰到下面这些问题:

  1. OutOfMemoryError,内存不足
  2. 内存泄露
  3. 线程死锁
  4. 锁争用(Lock Contention)
  5. Java进程消耗CPU过高
  6. ......
     这些问题在日常开发中可能被很多人忽视(比如有的人遇到上面的问题只是重启服务器或者调大内存,而不会深究问题根源),但能够理解并解决这些问题是Java程序员进阶的必备要求。本文将对一些常用的JVM性能调优监控工具hprof进行介绍。

二、hprof文件的生成

       生成hprof文件可以在DDMS( DDMS 的全称是DalvikDebug Monitor Service,是 Android 开发环境中的Dalvik虚拟机调试监控服务。提供测试设备截屏、查看特定进程正在运行的线程以及堆信息、Logcat、广播状态信息、模拟电话呼叫、模拟接收及发送SMS、虚拟地理坐标等服务 )选中进程点击窗口左上角的"dump hprof file"按钮来直接生成,也可以通过在程序加代码中来生成,以下通过设置生成hprof文件:
       我们希望在memory 溢出时候能自动生成heap dump文件,为此,我们在运行时候添加JVM 参数: 
        -XX:+HeapDumpOnOutOfMemoryError
        
  注:dump生成的.hprof文件默认放到了该项目目录下面。
  先构造一个实体类User,这个User类就是一般的java 类,然后我们构造一个ArrayList,然后在一个无限循环中一直放这个User类的实例,因为User类和ArrayList都在堆上,而ArrayList因为是强引用,所以无法被GC回收,(因为我们List一直在用并没有摧毁)所以一旦ArrayList所占用的堆内存填满整个heap size时候,heap就溢出了。
package com.deppon.tps;
public class User {
	private String name;
	private String sex;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
    public User( String name,String sex,int age){
        this.name=name;
        this.sex=sex;
        this.age=age;
    }
}
然后我们创建一个main方法就是上面的Test1类里面, 创建ArrayList,并且无限向其中添加User类对象的方法是:
package com.deppon.tps;
import java.util.ArrayList;
import java.util.List;
public class Test1 {
	public static void main(String[] args) {
		List<User> persons = new ArrayList<User> ();
        while( 1>0){
            persons.add( new User("liuhai","male",25));
        }
	}
}
当运行上述代码时候,堆溢出了,产生了heap dump文件(这里用VM参数指定了如果堆溢出则产生heap dump)


用 MAT(Memory Analyze Tool)工具--插件下载、安装及打开hprof文件见以下链接, 分析这个hprof文件(java_pid39340.hprof),我们发现了,它的确探测出了memory leak问题,如下:
  

如图所示,这里很清楚的表示,main()方法中有一个集合类型,,然后集合中的每一个元素都是com.charles.research.User的对象,并且每个对象的Shallow Heap和Retained Heap大小都为24byte。因为ArrayList一直存在,所以当对象足够多时候,就把heap弄满并且溢出了。这里创建了76340681个User对象,每个对象占据了24个byte,所以一共占据了24 * 7634068=183217632字节,差不多约为 174.72M 大小的堆空间。在这里 User对象的S hallow Size 和 Retained Size都为24byte呢?

我们要看下Shallow Size和Retained Size各是什么?

Shallow Size是对象本身占据的内存的大小,不包含其引用的对象。对于常规对象(非数组)的Shallow Size由其成员变量的数量和类型来定,而数组的ShallowSize由数组类型和数组长度来决定,它为数组元素大小的总和。

Retained Size=当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C,C就是间接引用) ,并且排除被GC Roots直接或者间接引用的对象

所以,我们这里的User类,因为我们机器是32位 WIN7系统,所以对象头占据8byte,它包含String对象引用(name),占据4byte,包含String对象引用(sex),占据4byte,包含一个int类型(age),占据4byte,所以一共占据8+4+4+4=20byte, 因为要补齐位数,所以最后尺寸为24byte. 这就是这个对象的本身大小(Shallow Heap)的大小。

小知识:为了说明补齐,大家也可以做实验,如果我们User中加一个String成员,那么User类大小仍然为24byte,因为这个新String对象的引用4byte刚好去填了补齐的那个坑,如果再加一个String成员,那么User类大小就直接从24byte升到32byte了,因为又产生了一个坑需要补齐。

而我们的User类中没有引入其他的类(不包括String,因为String直接被Root GC引用),所以回收User占据的内存就是回收User自身,所以Retained Heap大小等同于Shallow Heap大小。

三、tomcat中设置jvm参数

linux系统中

1.打开/tomcat_home/bin/catalina.sh文件 

2.加上:JAVA_OPTS="$JAVA_OPTS -server -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapdump"

如下图位置:

注:其中不设-XX:HeapDumpPath时,dump出的文件在/tomcat_home/bin目录下

Windows系统中

1.打开/tomcat_home/bin/catalina.bat文件

2.加上:set JAVA_OPTS=%JAVA_OPTS% -server -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapdump

如下图位置:




MAT下载:http://www.eclipse.org/mat/downloads.php
http://www.tuicool.com/articles/3yMN7z

资源下载链接为: https://pan.quark.cn/s/9ce3e35e0f39 MAT(Memory Analyzer Tool)是由Eclipse基金会开发的一款强大的Java堆内存分析工具,主要用于诊断Java应用程序中的内存问题,例如内存泄漏、内存占用过高以及对象生命周期管理等。MAT的核心功能之一是能够分析hprof文件。hprof是Java虚拟机(JVM)生成的一种标准内存剖析数据格式,记录了JVM运行时的内存信息,包括对象分配、存活状态和引用关系等。通过解析hprof文件,MAT可以清晰地呈现内存消耗情况,帮助开发者定位可能导致问题的对象和类。 MAT的主要功能包括:一是对象分配和生存时间分析,通过“对象分配”视图显示哪些类创建了最多对象及其生存时间,从而识别内存泄漏源头。二是支配树功能,该视图展示了内存中对象的关系,其中主导对象是其他对象所依赖的,通过查看支配树可以找出占据大量内存的对象及其关联。三是大型对象集视图,它列出了占用内存最多对象集合,便于快速识别潜在问题。四是泄漏嫌疑人报告,MAT会自动生成一份报告,分析可能的内存泄漏原因,包括疑似泄漏的类、静态字段和单例等。五是碎片分析,MAT能够区分对象自身的内存占用(Shallow Heap)和由该对象间接导致的内存占用(Retained Heap),帮助更好地理解内存消耗情况。六是对比分析,如果有多个内存快照,MAT可以进行对比,揭示内存状态变化,发现随时间推移出现的问题。七是复制和合并功能,允许用户复制或合并不同的hprof文件,便于在不同场景下进行比较和分析。八是哈希表视图,针对使用哈希表(如HashMap)导致的内存问题,MAT提供了专门的视图来分析其内容和内存占用。九是线程堆栈功能,MAT可以显示每个线程的堆栈信息,有助于定位与线程相关的内存问题。十是自定义查询功能,MAT支持类似SQL的
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值