摘要:java内存dump是jvm运行时内存的一份快照,利用它可以分析是否存在内存浪费,可以检查内存管理是否合理,当发生OOM的时候,可以找出问题的原因。那么dump文件的内容是什么样的呢?

JVM dump

java内存dump是jvm运行时内存的一份快照,利用它可以分析是否存在内存浪费,可以检查内存管理是否合理,当发生OOM的时候,可以找出问题的原因。那么dump文件的内容是什么样的呢?我们一步一步来

获取JVM dump文件

获取dump文件的方式分为主动和被动
i.主动方式:
1.利用jmap,也是最常用的方式:jmap -dump:[live],format=b,file=
2.利用jcmd,jcmd GC.heap_dump
3.使用VisualVM,可以界面操作进行dump内存
4.通过JMX的方式

MBeanServer server = ManagementFactory.getPlatformMBeanServer();
HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
mxBean.dumpHeap(filePath, live);

参考(https://www.baeldung.com/java-heap-dump-capture)
ii.被动方式:
被动方式就是我们通常的OOM事件了,通过设置参数-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=

dump文件分析

结构示意图

结构详解

dump文件是堆内存的映射,由文件头和一系列内容块组成

文件头

由musk, 版本,identifierSize, 时间4部分组成

  1. musk:4个byte,内容为'J', 'A', 'V', 'A'即JAVA

  2. version:若干byte,值有以下三种

" PROFILE 1.0\0",
" PROFILE 1.0.1\0",
" PROFILE 1.0.2\0"

3. identifierSize:4个byte数字,值为4或者8,表示一个引用所占用的byte数

4. time:8个byte,dump文件生成时间

说明:java一个类的成员变量有两种类型

  1. 基本类型(8种基本类型),它们占用byte数固定不变,每生成一个对象它们就需要给它们赋初始值,分配空间

  2. 是引用类型,表示一个对象,在类中只有一个引用,引用只是一个数值,所占用的空间大小为identifierSize,被引用对象即将在堆中的另一个地方
    例如定义一个类

public class Person {private int age;//4个byteprivate String name;//identifierSize个byteprivate double weight;//8个byte
}

当我们在new Person()的时候
它就需要申请一个空间,空间大小为 对象头大小+4+identifierSize+8个byte

对象大小的测量:
jdk提供一个测试对象占用内存大小的工具Instrumentation,但是Instrumentation没法直接引用到,需要通过agent来引用到
定义一个Premain类, javac Premain.java

//Premain.java
public class Premain {public static java.lang.instrument.Instrumentation inst;public static void premain(String args, java.lang.instrument.Instrumentation inst) {Premain.inst = inst;}
}

编写一个Manifest文件

manifest.mf
Manifest-Version: 1.0
Premain-Class: Premain
Can-Redefine-Classes: true
Can-Retransform-Classes: true

打包

jar -cmf manifest.mf premain.jar Premain.class

定义一个执行类, javac PersonTest.java

//PersonTest.java
public class PersonTest {public static void main(String[] args) throws Exception {Class clazz = Class.forName("Premain");if (clazz != null) {Person p = new Person();java.lang.instrument.Instrumentation inst = (java.lang.instrument.Instrumentation)clazz.getDeclaredField("inst").get(null);System.out.println("person size:[" + inst.getObjectSize(p) + "]B");System.out.println("class size:[" + inst.getObjectSize(p.getClass()) + "]B");}}
}

带agent执行

java -javaagent:premain.jar PersonTest

结果:

person size:[32]B
class size:[504]B

内容块

每个块都是块头和块体组成

块头

块头由1个byte的块类型,4个byte的时间time,4个byte的长度表示此内容块占用byte数
type类型一般有5种,字符串,类,栈桢,栈,及dump块

  1. 字符串,由identifierSize个byte的字符串id,后面是(length-identifierSize)个byte的字符串内容(后续对字符串是直接引用的这里面的id)

  2. 类,由4个byte的类序列(在栈桢中使用),identifierSize个byte的类id(解析类的时候用到),4个byte的序列id(暂未使用),identifierSize个byte的类名id

  3. 栈桢,由identifierSize个byte的桢id,identifierSize个byte的方法名id,identifierSize个byte的方法标识id,identifierSize个byte的类文件名id,4个byte的类序列,4个byte的行号

  4. 栈,由4个byte的栈序号,4个byte的线程序号,4个byte的桢数量,后面就是若干个identifierSize个byte的桢id

  5. dump块就是所有对象的内容了,每个对象由1个byte的子类型,和对象内容结成,子类型有6种,gc root, 线程对象,类,对象,基本类型数组,对象数组

gc root

gc root有4种结构,8种类型

  1. identifierSize个byte的对象id,类型有SYSTEM_CLASS,BUSY_MONITOR, 及未UNKNOWN

  2. identifierSize个byte的对象id,4个byte的线程序列号,类型有NATIVE_STACK,THREAD_BLOCK

  3. identifierSize个byte的对象id,4个byte的线程序列号,4个byte的栈桢深度,类型有JAVA_LOCAL,NATIVE_LOCAL

  4. identifierSize个byte的对象id,identifierSize个byte的global refId(暂未使用),类型有NATIVE_STATIC

    gc root示意图

    gc root为垃圾收集追溯的源头,每个gc root都指向一个初始对象,无法追溯的对象是要被回收掉的

系统类,只有classLoader为null的类才是gc root,每个类都是一个gc root
线程栈,线程中方法参数,局部变量都是gc root,每个对象都是一个gc root
系统保留对象,每个对象都是一个gc root

类对象

1、基本信息:

  1. identifierSize个byte的类对象id

  2. 4个byte的栈序列号,

  3. identifierSize个byte的父类对象id,

  4. identifierSize个byte的classLoader对象id,

  5. identifierSize个byte的Signer对象id,

  6. identifierSize个byte的protection domain对象id,

  7. identifierSize个byte的保留id1和id2,

  8. 4个byte的类实例对象大小,

  9. 2个byte的常量个数,后面是每个常量的,2个byte的下标,1个byte的常量类型,和若干个byte的内容,内容根据类型来决定(boolean/byte为1个byte, char/short为2个byte,float/int为4个byte, double/long为8个byte,引用类型为identifierSize个byte)

  10. 2个byte的静态变量个数,后面是每个静态变量的,identifierSize个byte的变量名id, 1个byte的变量类型,和若干个byte的内容,内容根据类型来决定(见类对象基本信息的第9条)

  11. 2个byte的成员变量个数,后面是每个成员变量的,identifierSize个byte的变量名id,1个byte的变量类型

2、说明:
1、类里面的常量很多地方都没有用上,所以常量个数一般为0
2、类的静态变量的名称类型及值是放在类对象里面的,成员变量的名称和类型也是放在类对象里面的,但是实例的值是放在实例对象里面的

实例对象

1、基本信息:

  1. identifierSize个byte的实例对象id

  2. 4个byte的栈序列号

  3. identifierSize个byte的类id

  4. 4个byte的占用字节数

  5. 实例的变量的值

2、说明:

  1. 实例的值为实例对象的成员变量值,顺序为当前类的变量值,顺序为类对象基本信息中第11条中的顺序,然后是父类的变量值

  2. 变量的值基本类型都有默认值,引用类型默认值为0,占用字节数(见类对象基本信息的第9条)

基本类型数组

1、基本信息:

  1. identifierSize个byte的数组对象id

  2. 4个byte的栈序列号

  3. 4个byte的数组长度

  4. 1个byte的元素类型

  5. 元素的值列表

2、说明:

  1. 元素的值(见类对象基本信息的第9条)

对象数组

1、基本信息:

  1. identifierSize个byte的数组对象id

  2. 4个byte的栈序列号

  3. 4个byte的数组长度

  4. identifierSize个byte的元素类id

  5. 元素的值列表

内存分配

当一个线程启动的时候,进程会去系统内存生成一个线程栈
每当发生一次方法调用,就会向栈中压入一个栈桢,当方法调用完之后,栈桢会退出
在运行过程中,如果有对象的new操作的时候,进程会去堆区申请一块内存
关于运行时内存的详细情况,可以查找相关的资料

内存回收规则

如果一个对象不能骑过gc root引用可达,那么这个对象就可能要被回收
对象回收规则包括

  1. 实例属性被实例引用,只有当实例被回收了实例属性才能被回收(只针对强引用)

  2. 类对象被实例引用,只有当一个类的所有实例都被回收了,类才能被回收

  3. 类对象的父类,classLoader对象,signer对象, protection domain对象被类引用,只有当类被回收了,这些才能被回收

  4. 局部变量(线程栈中)的作用域为一个大括号

    public void test(){
    Object a = new Object();//obj 1
    Object b = new Object();//obj 2
    {
    Object c = new Object();//obj 3
    a = null;//obj 1可以被回收了
    }//obj 3可以回收了
    }//obj 2可以被回收了

分析工具简介

分析dump文件,我们可以用jdk里面提供的jhat工具,执行

jhat xxx.dump

jhat加载解析xxx.dump文件,并开启一个简易的web服务,默认端口为7000,可以通过浏览器查看内存中的一些统计信息

一般使用方法

1、浏览器打开http:/127.0.0.1:7000

会列出一些功能,包括package下面各个类的概览,及各个功能导航
2、点击页面的堆内存统计

有一个表格,对象类型,实例个数,实例所占用内存大小,哪种类型的对象占用了内存最多一目了然
3、点击其中认为内存消耗太多的类名查看类详情

主要展现该类下面各个实例的大小,以及一些链接导航
4、点击references summary by type

如果某种类型的对象太多,那么有可能是引用它的那个类的对象太多

基本上一些简单页面的查询,结合原代码,就可以初步定位内存泄漏的地方

点击这里→了解更多精彩内容

相关推荐

Java从x86到Arm跨平台,实战一下!

9 个Java 异常处理的规则!

挑战10个最难的Java面试题(附答案)

手把手教你在鲲鹏上使用编程语言——Java、Python

Android手机打造你的Python&Java开发工具!

【华为云技术分享】干货分享丨jvm系列:dump文件深度分析相关推荐

  1. jmap 文件解析_干货分享丨jvm系列:dump文件深度分析

    摘要:java内存dump是jvm运行时内存的一份快照,利用它可以分析是否存在内存浪费,可以检查内存管理是否合理,当发生OOM的时候,可以找出问题的原因.那么dump文件的内容是什么样的呢? JVM ...

  2. 【重磅资料】ArchSummit全球架构师峰会·2019华为云技术专场资料下载

    ArchSummit全球架构师峰会是InfoQ中国团队推出的重点面向高端技术管理者.架构师的技术会议,54%参会者拥有8年以上工作经验.ArchSummit聚焦业界强大的技术成果,秉承"实践 ...

  3. 【华为云技术分享】三大前端技术(React,Vue,Angular)探密(下)

    [华为云技术分享]三大前端技术(React,Vue,Angular)探密(上) [Angular] Angular(通常被称为 "Angular 2+"或 "Angula ...

  4. 【华为云技术分享】“技术-经济范式”视角下的开源软件演进剖析-part 1

    前言 以互联网为代表的信息技术的迅猛发展对整个经济体系产生了巨大的影响.信息技术的发展一方面使知识的积累和传播更加迅速,知识爆炸性的增长:另一方面,使信息的获取变得越来越容易,信息交流的强度逐渐增加, ...

  5. 【华为云技术分享】“技术-经济范式”视角下的开源软件演进剖析-part 3

    4. 微观层面 4.1 个体动机 在开源软件发展之初, 商业组织的投入很少甚至没有, 完全是靠Richard Stallman 或者 linus Torvalds 这样的个人在努力推动开源软件艰难前行 ...

  6. 【华为云技术分享】数据赋能,如何精细化保障企业大数据安全

    云湖湖导读:随着企业业务的不断发展,企业大数据资产在企业辅助决策.用户画像.推荐系统等诸多业务流程中扮演着越来越重要的作用,如何保证企业大数据在满足各业务部门数据访问需求的同时又能精细化保障数据访问安 ...

  7. 【华为云技术分享】六步教你玩转DevOps上华为云DevCloud实践

    摘要:在"DevOps能力之屋(Capabilities House of DevOps)"中,华为云DevCloud提出(工程方法+最佳实践+生态)×工具平台=DevOps能力. ...

  8. 云栖盘点:2022 云网络产业干货分享

    11 月 4 日,2022 杭州·云栖大会"互联网与飞天技术创新峰会"上,阿里云智能云网络产品线总经理祝顺民结合飞天洛神云网络的发展历程,探索企业面对数字化和全球化发展的网络新边界 ...

  9. 华为云技术开放日(第三季)活动报道

    智能共生,链接未来 | 华为云技术开放日(第三季)精彩回顾 7 月 29日-8 月 12 日,由华为云与中生代技术社区联合主办的华为云技术开放日(第三季)圆满落下帷幕.本次技术开放日邀请了华为云 MV ...

最新文章

  1. 企业网络推广专员浅析是否网站权重越高企业网络推广效果越好?
  2. 多核处理器_手机处理器性能排行:骁龙865第四,麒麟9000拿下第二
  3. 淘宝客程序 —— 突破了传统淘宝客程序对自动采集商品收费的模式
  4. expect 赋值shell变量_Shell处理字符串常用技巧终结篇
  5. WordPress程序伪静态规则(Nginx/Apache)及二级目录规则
  6. aws rds监控慢sql_估算AWS RDS SQL Server成本
  7. MySQL 基础 —— 字符串处理
  8. C#正则怎么判断字符串中是否有汉字
  9. Python数据库操作——连接MySQL
  10. ZStack实践汇 | ZStack部署实战之VDI异构部署
  11. 超级终端连接华为交换机_Win8系统如何使用超级终端连接华为交换机?
  12. Anroid 开发so文件找不到问题-例高德地图SDK提示com.autonavi.amap.mapcore.MapCore.nativeNewInstance问题
  13. 下载《阿里巴巴Java开发手册(详尽版)1.4.0》 与 码出高效,码出质量
  14. python 多分类情感词典_情感分类(sentiment classification)推荐使用什么算法和软件包?...
  15. OpenCV识别图形以及常用函数处理
  16. 方维众筹1.7短信插件短信接口开发
  17. 第二章第三章 查找和排序(上)
  18. 离散化 Gym 101964E Fishermen
  19. win7电脑蓝屏没有修复计算机,win7电脑蓝屏怎么办
  20. DPU-PYNQ Ultra96v2安装使用说明

热门文章

  1. 修复 IE 的文本3像素偏移Bug
  2. 重读读书笔记的重要性
  3. matlab中if可以判断或语句吗,matlab中if 语句后面的判别式不能是算术表达式?或者说变量?...
  4. vs怎么写html5页面,怎么使用vscode写html5
  5. python读取csv数据画直方图_用csv文件作为inpu在python中绘制直方图
  6. PX4 编译分析之Airframe文档生成
  7. 纯JS前端分页方法(JS分页)
  8. 十六进制报文用wireshark打开
  9. Android基础学习第二篇—Activity
  10. java新入手的三十个基本概念