java jvm dump文件_干货分享丨jvm系列:dump文件深度分析

2023-11-20

摘要: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);

ii.被动方式:

被动方式就是我们通常的OOM事件了,通过设置参数-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=

dump文件分析

结构示意图

3f23e1d915487e9c1003d4acf2880323.png

结构详解

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一个类的成员变量有两种类型

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

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

例如定义一个类

public classPerson {private int age;//4个byte

private String name;//identifierSize个byte

private double weight;//8个byte

}

当我们在new Person()的时候

它就需要申请一个空间,空间大小为 对象头大小+4+identifierSize+8个byte

对象大小的测量:

jdk提供一个测试对象占用内存大小的工具Instrumentation,但是Instrumentation没法直接引用到,需要通过agent来引用到

定义一个Premain类, javac Premain.java

//Premain.java

public classPremain {public staticjava.lang.instrument.Instrumentation inst;public static voidpremain(String args, java.lang.instrument.Instrumentation inst) {

Premain.inst=inst;

}

}

编写一个Manifest文件

manifest.mf

Manifest-Version: 1.0Premain-Class: Premain

Can-Redefine-Classes: trueCan-Retransform-Classes: true

打包

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

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

//PersonTest.java

public classPersonTest {public static voidmain(String[] args) throws Exception {

Class clazz= Class.forName("Premain");if (clazz != null) {

Person p= newPerson();

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]Bclass size:[504]B

内容块

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

块头

块头由1个byte的块类型,4个byte的时间time,4个byte的长度表示此内容块占用byte数

type类型一般有5种,字符串,类,栈桢,栈,及dump块

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

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

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

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

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

gc root

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

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

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

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

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

gc root示意图

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

e8cff6159b45986ae3ef0a61f55c6a69.png

系统类,只有classLoader为null的类才是gc root,每个类都是一个gc root

线程栈,线程中方法参数,局部变量都是gc root,每个对象都是一个gc root

系统保留对象,每个对象都是一个gc root

类对象

1、基本信息:

identifierSize个byte的类对象id

4个byte的栈序列号,

identifierSize个byte的父类对象id,

identifierSize个byte的classLoader对象id,

identifierSize个byte的Signer对象id,

identifierSize个byte的protection domain对象id,

identifierSize个byte的保留id1和id2,

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

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)

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

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

2、说明:

(1)类里面的常量很多地方都没有用上,所以常量个数一般为0

(2)类的静态变量的名称类型及值是放在类对象里面的,成员变量的名称和类型也是放在类对象里面的,但是实例的值是放在实例对象里面的

实例对象

1、基本信息:

identifierSize个byte的实例对象id

4个byte的栈序列号

identifierSize个byte的类id

4个byte的占用字节数

实例的变量的值

2、说明:

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

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

基本类型数组

1、基本信息:

identifierSize个byte的数组对象id

4个byte的栈序列号

4个byte的数组长度

1个byte的元素类型

元素的值列表

2、说明:

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

对象数组

1、基本信息:

identifierSize个byte的数组对象id

4个byte的栈序列号

4个byte的数组长度

identifierSize个byte的元素类id

元素的值列表

内存分配

e6dd4c2ce2312273589a369156b24e4b.png

当一个线程启动的时候,进程会去系统内存生成一个线程栈

每当发生一次方法调用,就会向栈中压入一个栈桢,当方法调用完之后,栈桢会退出

在运行过程中,如果有对象的new操作的时候,进程会去堆区申请一块内存

关于运行时内存的详细情况,可以查找相关的资料

内存回收规则

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

对象回收规则包括

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

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

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

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

public voidtest(){

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

12ef993aae125a3ad1af26c63d36c99e.png

会列出一些功能,包括package下面各个类的概览,及各个功能导航

2、点击页面的堆内存统计

94744e2d3dd985c8dc63d7b20c9d554e.png

有一个表格,对象类型,实例个数,实例所占用内存大小,哪种类型的对象占用了内存最多一目了然

3、点击其中认为内存消耗太多的类名查看类详情

cae37877bd6b7e8aa63f79845c8bf8b7.png

主要展现该类下面各个实例的大小,以及一些链接导航

4、点击references summary by type

bebeccb1cbda43fe872de7bb14340f8e.png

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

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

综上,dump文件结构还是比较简单的,这对于分析线程的执行情况非常有用,也是每一个Java程序员必须掌握的高级技能之一,你学会了吗?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java jvm dump文件_干货分享丨jvm系列:dump文件深度分析 的相关文章

  • PLINQ并行查询效率的简单分析

    PLINQ并行查询效率的简单分析 假设执行一次查询需要花费的时间比较大 那我们可以采用PLINQ并行查询来进行提速 并行查询 就是利用多核计算机并行执行查询语句来进行提速 这很好理解 一个工人工作慢 那就多叫几个工人同时进行工作 这样工作的
  • php 实现微信消息时间,在微信小程序中如何实现时间功能

    这篇文章主要介绍了微信小程序使用picker实现时间和日期选择框功能 结合实例形式分析了微信小程序picker组件进行日期与时间选择的相关操作技巧 并附带源码供读者下载参考 需要的朋友可以参考下 本文实例讲述了微信小程序使用picker实现
  • 选择结构程序设计和循环控制(if语句,switch语句,条件运算符,for循环,while及do while语句,break,continue,goto语句)折半查找法及猜数字游戏带你巩固理解

    本章我们来迅速学习一下选择语句和循环语句 首先我们来了解何为语句 C语言中语句可以分为以下五类 1 表达式语句 2 函数调用语句 3 控制语句 4 复合语句 5 空语句 这篇文章我们主要讲的是控制语句 控制语句 控制语句主要用于控制程序的运
  • IDEA 三种注释生成方式

    三种注释方式 行注释 块注释 方法或类说明注释 一 快捷键 Ctrl 使用Ctrl 添加行注释 再次使用 去掉行注释 二 演示代码 if hallSites null hallSites size gt 0 行注释 最大行号 int max
  • 【Python】基于Python利用熵权法计算数据权重——一个简单的图形用户界面编程

    目录 1 简介 2 技术流程 3 数据 4 代码 4 1 代码 极差标准化 4 2 代码 熵权法赋权 5 实验操作与流程 6 关于数据获取 1 简介 师弟又催我给他公众号写文了 这次还点名要这个题目 所以我就先到自己的博客里写写练练手 下面
  • ​Java 输入一个字符串,统计其中字符 A 的数量并输出。

    题目描述 输入一个字符串 统计其中字符 AA 的数量并输出 输入 输入一个不带空格的字符串 字符串长度不超过 100 输出 输出字符串中字符 A 的数量 样例输入 AabdkeaoektA 样例输出 2 import java util S
  • sublime text 3上使用Git连接Github

    首先下载的sublime text 3我是在PHP中文网下载的 是汉化版 一进去就有git插件 之前很久下过的好像不能使用插件 所以我就下了最新的汉化版 进去就有git插件 再者就是git要自己下载一下安装 配置好path环境变量 也就是c
  • 点击按钮复制链接

    做点击按钮复制链接 网上找的方法是用原生js document execCommand Copy window clipboardData setData Text url value 发现微信上存在不兼容 在安卓和PC段都可以 但是在苹果
  • 2023问题汇总

    问题汇总 Linux相关 1 vim 修改挂载文件时 报错 read only filesystem 2 root 用户密码无法更改 3 linux 用户被锁定 4 linux 查看登录日志 其他小问题 1 linux 的dns 修改配置
  • 企微报错60020

    errcode 60020 errmsg not allow to access from your ip hint 1655882753557010848204971 from ip more info at https open wor
  • wazuh安装手册

    一 wazhu部署架构 1 服务器上运行的Agent端会将采集到的各种信息通过加密信道传输到管理端 2 管理端负责分析从代理接收的数据 并在事件与告警规则匹配时触发警报 3 LogStash会将告警日志或者监控日志发送到Elasticsea
  • 第九章 细分着色器

    第九章 细分着色器 细分面片 细分着色器只能处理面片 patch 类型的图元 如果启用细分着色器 将其他类型图元传递给它会产生GL INVALID OPERATION错误 如果没有启用细分着色器 那么渲染面片数据也会得到GL INVALID
  • 【JFinal最省代码的框架】JFinal+Bootstrap实现后台管理系统主页

    原文 JFinal最省代码的框架 JFinal Bootstrap实现后台管理系统主页 源代码下载地址 http www zuidaima com share 1893049233067008 htm
  • 爱情和婚姻的区别

    有一天 柏拉图问老师苏格拉底什么是爱情 老师就让他先到到麦田里去 摘一棵全麦田里最大最金黄的麦穗来 期间只能摘一次 并且只可向前走 不能回头 柏拉图于是按照老师说的去做了 结果他两手空空的走出了田地 老师问他为什么摘不到 他说 因为只能摘一
  • 【DevOps视频笔记】6 - 7. Jenkins 介绍 和 安装

    一 Integrate 工具 二 Jenkins 介绍 1 Jenkins 最主要的工作 2 CI CD 可以理解为 2 1 CI 过程 2 2 CD 过程 三 Jenkins 安装 1 安装准备工作 2 安装 Jenkins Stage
  • 环境配置--解决torch.cuda.is_available()返回:False

    在网上很多都说是因为pytorch版本和CUDA不匹配造成的 但对于我的情况并不是 而是因为在官网默认下载到了的pytorch是cpu版本 真坑 另外在pycharm默认下载到的pytorch 1 9 0也是cpu版本 用不了cuda 1
  • 计算机设计大赛答辩提问,电子设计大赛答辩常见问题合集

    电子设计大赛答辩常见问题合集 由会员分享 可在线阅读 更多相关 电子设计大赛答辩常见问题合集 2页珍藏版 请在人人文库网上搜索 1 答辩常见问题合集1 本课题的选课背景 意义等等 这个论文中有的 也都是一些套话 我就不答了 我整理的都是技术
  • PLSQL创建新用户并导入导出.dmp文件

    一 登录管理员账号 用户名 密码 登录身份 说明 system manager SYSDBA 或 NORMAL 不能以 SYSOPER 登录 可作为默认的系统管理员 sys change on install SYSDBA 或 SYSOPE
  • 电路设计相关

    本人才疏学浅 孤陋寡闻 下文若有不当之处 还请赐教 1 一些概念 施密特触发器 施密特触发器采用电位触发方式 其状态由输入信号电位维持 对于负向递减和正向递增两种不同变化方向的输入信号 施密特触发器有不同的阈值电压 对于标准施密特触发器 当

随机推荐

  • 天眼使用指南--分析平台

    天眼分析平台 提供全面的溯源分析能力 涵盖图中模块 负责存储日志 分为三类 告警日志 告警日志 来自探针和沙箱的告警 探针的告警可以记录双向完整对话 如果网络流量中没有恶意信息 就会储存一些关键信息 如http请求部分状态码 tcp上下前一
  • 用python批量插入clickhouse

    用python批量插入clickhouse 以下是一个示例代码 演示了如何使用clickhouse driver模块实现批量插入和分布式查询 import clickhouse driver import random connect to
  • C语言函数调用过程

    文 读书笔记 C语言函数调用过程 c legendmohe 2015年07月12日发布 推荐 0 推荐 收藏 0 收藏 392 浏览 本文是 老码识途 第一章的读书笔记 函数调用 例子代码如下所示 int Add int x int y i
  • 什么是参数模型(LR)与非参数模型(SVM)

    什么是参数模型 LR 与非参数模型 SVM 在统计学中 参数模型通常假设总体 随机变量 服从某一个分布 该分布由一些参数确定 比如正太分布由均值和方差确定 在此基础上构建的模型称为参数模型 非参数模型对于总体的分布不做任何假设 只是知道总体
  • jQuery Validate验证框架详解

    jQuery校验官网地址 http bassistance de jquery plugins jquery plugin validation 一 导入js库 注 返回web项目的根路径 二 默认校验规则 1 required true
  • 测试大姐趁我下班点又提了个bug!前端你咋多个options请求?

    测试大姐提了个bug 为什么你多了个options请求 1 下班前的寂静 刚准备下班呢 测试大姐又给我提个bug 你看我这就操作了一次 network里咋有两个请求 我心一惊 不可能啊 我代码明明就调用一次后端接口 咋可能两个请求 打开她的
  • floor(),ceil()函数

    地板 天花板函数 均包含在math h中 意思分别为 返回不大于形参的最小整数和不小于形参的最大整数 include
  • Git冲突导致的Please commit your changes or stash them before you merge

    Git冲突导致的Please commit your changes or stash them before you merge 用git pull来更新代码的时候 遇到了下面的问题 error Your local changes to
  • js检查数据类型的方法

    1 typeof 这是最常用的基本数据类型检测的方法 console log typeof string console log typeof 1 number console log typeof true boolean console
  • spring boot最新教程(五):404错误500错误统一处理

    Spring Boot默认使用嵌入式Tomcat 默认没有页面来处理404等常见错误 因此 为了给用户最佳的使用体验 404 500等常见错误需要我们自定义页面来处理 我们需要用org springframework boot contex
  • 威动服务器如何添加文件夹,威动服务器如何设置

    威动服务器如何设置 内容精选 换一换 华为云提供两种连接方式通过SQL Server客户端连接实例 非SSL连接和SSL连接 其中 SSL连接实现了数据加密功能 具有更高的安全性 安装SQL Server客户端请参见如何安装SQL Serv
  • 如何使用 Docker 部署 Caddy Web 服务器

    Caddy是一种流行的现代 Web 服务器 专为高性能和内存安全而设计 它是用 Go 编写的 运行时没有依赖关系 内置支持使用 Markdown 进行静态站点渲染 并提供自动 HTTPS Caddy 专注于提供简单的服务器管理体验 默认情况
  • Vue + Element UI 前端篇(十一):第三方图标库

    Vue Element UI 实现权限管理系统 前端篇 十一 第三方图标库 使用第三方图标库 用过Elment的同鞋都知道 Element UI提供的字体图符少之又少 实在是不够用啊 幸好现在有不少丰富的第三方图标库可用 引入也不会很麻烦
  • HDFS常用命令

    1 hdfs dfs与hadoop fs 命令的形式 hdfs dfs linux命令 这与linux中命令操作是一样的 hadoop fs等同于hdfs dfs 2 Hadoop命令 hadoop classpath 打印当前hadoop
  • 程序员的自我修养(九)虚拟内存空间

    进程的虚拟地址 每个程序被运行起来以后 它将拥有自己独立的虚拟地址空间 这个虚拟地址空间的大小由计算机的硬件平台决定 具体的说是由CPU的位数决定 对于Linux系统来说 它的进程虚拟空间的划分 1GB 操作系统 3GB 进程 对于Wind
  • derby mysql 性能_derby的三大缺陷

    derby数据库的嵌入式特性让人很流口水 但是 我刚打算将其用进我的项目中 却发现它没有好的分页查询方式 每次都返回所有符合条件的记录 oracle有rownum mysql有limit sqlserver好歹也有个top 汗啊汗 看来不爽
  • 【ROS入门学习01

    ROS命令行工具的使用 可以配合古月居的ROS入门教程来学习实践 文章目录 ROS命令行工具的使用 一 roscore 二 rosrun 三 rqt graph 四 rosnode 五 rostopic 六 rosmsg 七 rosserv
  • 客观面试题--35.Mybatis和hibernate的优缺点?

    Hibernate Hibernate 是当前最流行的ORM框架 对数据库结构提供了较为完整的封装 Mybatis Mybatis同样也是非常流行的ORM框架 主要着力点在于POJO 与SQL之间的映射关系 其次具体从几个方面说一下两者的区
  • 自己动手部署以太坊联盟链

    一个区块链学习项目 GitHub https github com xianfeng92 Love Ethereum 假设已经在Ubunbu 14 04 LTS上安装好了以太坊客户端Geth 使用Geth部署以太坊联盟链 以太坊Geth客户
  • java jvm dump文件_干货分享丨jvm系列:dump文件深度分析

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