Heap堆分析(堆转储、堆分析)
一、堆直方图
减少内存使用时一个重要目标,在堆分析上最简单的方法是利用堆直方图。通过堆直方图我们可以快速看到应用内的对象数目,同时不需要进行完整的堆转储(因为堆转储需要一段时间来分析,而且会消耗大量磁盘空间)。
直方图擅长识别由分配了一两个特定类的过多实例所引发的问题。例如应用中的内存压力是由一些特定的对象类型引起的,利用堆直方图可以很快就能看出端倪。
1.1、通过jcmd获得
堆直方图可以通过jcmd命令获得:
[ciadmin@2-103test_app ~]$ jcmd 26964 GC.class_histogram | more
26964: num #instances #bytes class name
----------------------------------------------
1: 91488 21270064 [C
2: 9058 18963152 [B
3: 80620 2579840 java.util.concurrent.ConcurrentHashMap$Node
4: 24081 2119128 java.lang.reflect.Method
5: 86860 2084640 java.lang.String
6: 13013 1444264 java.lang.Class
7: 24376 1170048 org.aspectj.weaver.reflect.ShadowMatchImpl
8: 26822 1072880 java.util.LinkedHashMap$Entry
9: 553 921168 [Ljava.util.concurrent.ConcurrentHashMap$Node;
10: 15903 890568 java.util.LinkedHashMap
11: 12092 847832 [Ljava.util.HashMap$Node;
12: 307 829712 [J
13: 24376 780032 org.aspectj.weaver.patterns.ExposedState
14: 12621 718696 [Ljava.lang.Object;
15: 5433 686400 [I
16: 36341 581456 java.lang.Object
17: 17746 567872 java.util.HashMap$Node
18: 1267 476392 java.lang.Thread
19: 13207 422624 java.lang.ThreadLocal$ThreadLocalMap$Entry
20: 2516 270336 [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;
说明:
1、字段说明
- [C:字符数组
- [B:字节数组
- [Ljava.lang.Object:Object数组
2、GC.class_histogram输出的仅包含活跃对象
1.2、通过jmap获得
命令为:jmap -histo process_id
jmap的输出中包含会被回收的对象(死对象)。要在看到直方图之前强制执行一次Full GC,可以转而运行下面的命令:
如下,在命令行中增加:live参数后,输出的直方图是Full GC之后的数据
[ciadmin@2-103test_app ~]$ jmap -histo:live 26964 | more num #instances #bytes class name
----------------------------------------------
1: 91488 21270064 [C
2: 9058 18963152 [B
3: 80620 2579840 java.util.concurrent.ConcurrentHashMap$Node
4: 24081 2119128 java.lang.reflect.Method
5: 86860 2084640 java.lang.String
6: 13013 1444264 java.lang.Class
7: 24376 1170048 org.aspectj.weaver.reflect.ShadowMatchImpl
8: 26822 1072880 java.util.LinkedHashMap$Entry
9: 553 921168 [Ljava.util.concurrent.ConcurrentHashMap$Node;
10: 15903 890568 java.util.LinkedHashMap
11: 12092 847832 [Ljava.util.HashMap$Node;
12: 307 829712 [J
13: 24376 780032 org.aspectj.weaver.patterns.ExposedState
14: 12621 718696 [Ljava.lang.Object;
15: 5433 686400 [I
16: 36341 581456 java.lang.Object
17: 17749 567968 java.util.HashMap$Node
18: 1267 476392 java.lang.Thread
19: 13207 422624 java.lang.ThreadLocal$ThreadLocalMap$Entry
20: 2516 270336 [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;
21: 8056 257792 java.util.LinkedList
22: 11664 247432 [Ljava.lang.Class;
23: 4397 187064 [Ljava.lang.String;
24: 1945 186720 org.springframework.beans.GenericTypeAwarePropertyDescriptor
25: 5631 180192 java.lang.ref.WeakReference
26: 3630 174240 java.util.HashMap
直方图非常小,但获取直方图也需要几秒时间。性能测试时需要注意它。
二、堆转储
直方图擅长识别由分配了一两个特定类的过多实例所引发的问题,但是要深度分析,就需要堆转储了。
2.1、使用jcmd进行堆转储
[ciadmin@2-103test_app pos-gateway-cloud]$ jcmd 26964 GC.heap_dump /home/ciadmin/pos-gateway-cloud/heap_dump.hprof
26964:
Heap dump file created
2.2、使用jmap进行堆转储
[ciadmin@2-103test_app pos-gateway-cloud]$ jmap -dump:live,file=/home/ciadmin/pos-gateway-cloud/heap_dump2.hprof 26964
Dumping heap to /home/ciadmin/pos-gateway-cloud/heap_dump2.hprof ...
Heap dump file created
jmap中包含live选项,会在堆转储前执行一次Full GC;jcmd默认就会这么做。如果因为某些原因,不希望包含其他对象(即死对象),可以在jcmd命令的最后加上-all。
2.3、自动堆转储
OutOfMemoryError是不可预料的,我们很难确定应该何时获得堆转储。有几个JVM标志可以起到帮助。
-XX:+HeapDumpOnOutOfMemoryError该标志默认为false,打开该标志,JVM会在抛出OutOfMemoryError时创建堆转储。
-XX:HeapDumpPath=<path>该标志知道了堆转储将被写入的位置,默认为当前工作目录下生产java_pid<pid>.hprof文件。
-XX:+HeapDumpAfterFullGC 这会在运行一次Full GC后生成一个堆转储文件。
-XX:+HeapDumpBeforeFullGC 这会在运行一次Full GC之前生成一个堆转储文件。
有的情况下,(入帮,因为执行了多次Full GC)会生成多个堆转储文件,这时JVM会在堆转储文件的名字上附加一个序号。
这两条命令都会在指定目录下创建一个命名为*.hprof的文件。生成之后,有很多工具可以打开该文件。以下是三个最常见的工具。
三、堆转储文件分析工具
jhat
这是最原始的分析工具,它会读取堆转储文件,并运行一个小型的HTTP服务器,该服务器运行你通过一系列网易链接查看堆转储信息。
[ciadmin@2-103test_app pos-gateway-cloud]$ jhat heap_dump.hprof
Reading from heap_dump.hprof...
Dump file created Mon Mar 05 18:33:10 CST 2018
Snapshot read, resolving...
Resolving 751016 objects...
Chasing references, expect 150 dots......................................................................................................................................................
Eliminating duplicate references......................................................................................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
找一台带浏览器的机器访问它,http://ip:7000
更多信息见《九、jdk工具之jhat命令(Java Heap Analyse Tool)、jhat之一:对dump的结果在浏览器上展示》
jvisualvm
jvisualvm的监视(Monitor) 选项卡可以从一个运行中的程序获得堆转储文件,也可以打开之前生成堆转储文件。
更多信息见《八、jdk工具之JvisualVM、JvisualVM之一--(visualVM介绍及性能分析示例)》
mat
开源的EclipseLink内存分析器工具(EclipseLink Memory Analyzer Tool,mat)可以加载一个或多个堆转储文件并执行分析。它可以生成报告,向我们建议可能存在问题的地方,也可以用于流量堆,并对堆执行类SQL的查询。
特别指出的是:mat内置一功能:如果打开了两个堆转储文件,mat有一个选项用来计算两个堆中的直方图之间的差别。
更多信息见《mat之一--eclipse安装Memory Analyzer》
对堆的第一遍分析通常涉及保留内存。一个对象的保留内存,是指回收该对象可以释放出的内存量。
关于保留内存相关知识见《GC之二--GC是如何回收时的判断依据、shallow(浅) size、retained(保留) size、Deep(深)size》
四、内存溢出错误
在下面情况下,jvm会抛出内存溢出错误(OutOfMemeoryError):
- JVM没有原生内存可用;
- 永久代(在java7和更早的版本中)或元空间(java8)内存不足;
- java堆本身内存不足--对于给定的堆空间而言,应用中活跃对象太多;
- JVM执行GC耗时太多;
1、原生内存不足
其原因与堆根本无关。在32位的JVM中,一个进程的最大内存是4GB,如果指定一个非常大的堆大小,比如说3.8GB,使应用的大小很接近4GB的限制,这很危险。
2、永久代或元空间内存不足
首先与堆无关,其根源可能有两种情况:
- 第一种情况是应用使用的类太多,超出了永久代的默认容纳范围;解决方案:增加永久代的大小
- 第二种情况相对来说有点棘手:它涉及类加载器的内存泄漏。这种情况经常出现于Java EE应用服务器中。类加载导致内存溢出可以通过堆转储分析,在直方图中,找到ClassLoader类的所有实例,然后跟踪他们的GC根,看哪些对象还保留了对它们的引用。
示例:
3、堆内存不足
当确实是堆内存本身不足时,错误信息会这样:
OutOfMemoryError:Java heap space
可能的原因有:
1、活跃对象数目在为其配置的堆空间中已经装不下了。
2、也可能是应用存在内存泄漏:它持续分配新对象,却没有让其他对象退出作用域。
不管哪种情况,要找出哪些对象消耗的内存最多,堆转储分析都是必要的;
4、达到GC的开销限制
JVM抛出OutOfMemoryError的最后一种情况是JVM任务在执行GC上花费了太多时间:
OutOfMemoryError:GC overhead limit exceeded
当满足下列所有条件时就会抛出该错误:
1、花在Full GC的时间超出了-XX:GCTimeLimit=N标志指定的值。默认为98
2、一次Full GC回收内存量少于-XX:GCHeapFreeLimit=N标志指定的值。默认值为2(2%)
3、上面两个条件连续5次Full GC都成立(这个值无法调整)
4、-XX:+UseGCOverhead-Limit标志为true(默认也为true)
这四个条件必须都满足。一般来说,连续5次Full GC以上,不一定会抛异常。即使98%时间在Full GC上,但每次GC期间释放的堆空间会超过2%,这种情况下可以增加-XX:GCHeapFreeLimit的值。
还请注意,如果前两个条件连续4次Full GC周期都成立,作为释放内存的最后一搏,JVM中所有的软引用都会在第五次Full GC之前被释放。这往往会防止该错误,因为第五次Full GC很可能会释放超过2%的堆内存(假设该应用使用了软引用)。
Heap堆分析(堆转储、堆分析)的更多相关文章
- 使用 Eclipse Memory Analyzer 进行堆转储文件分析
Eclipse Memory Analyzer(MAT)是著名的跨平台集成开发环境 Eclipse Galileo 版本的 33 个组成项目中之一,它是一个功能丰富的 JAVA 堆转储文件分析工具,可 ...
- mat 使用 分析 oom 使用 Eclipse Memory Analyzer 进行堆转储文件分析
概述 对于大型 JAVA 应用程序来说,再精细的测试也难以堵住所有的漏洞,即便我们在测试阶段进行了大量卓有成效的工作,很多问题还是会在生产环境下暴露出来,并且很难在测试环境中进行重现.JVM 能够记录 ...
- [Android Memory] 使用 Eclipse Memory Analyzer 进行堆转储文件分析
转载地址:http://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-ma/index.html Eclipse Memory Analyzer ...
- 源码分析:Java堆的创建
虚拟机在内存中申请一片区域,由虚拟机自动管理,用来满足应用程序对象分配的空间需求,即堆空间. 由于程序运行的局部特性,程序创建的大多数对象都具有非常短的生命周期,而程序也会创建一些生命周期特别长的对象 ...
- C#中堆和栈的区别分析(有待更新总结)
转载:http://blog.csdn.net/zevin/article/details/5721495 一.预备知识-程序的内存分配 一个由C/C++编译的程序占用的内存分为以下几个部分 1.栈区 ...
- Fortify Audit Workbench 笔记 Privacy Violation: Heap Inspection 隐私泄露(堆检查)
Privacy Violation: Heap Inspection 隐私泄露(堆检查) Abstract 将敏感数据存储在 String 对象中使系统无法从内存中可靠地清除数据. Explanati ...
- 堆(Heap)和二叉堆(Binary heap)
堆(Heap) The operations commonly performed with a heap are: create-heap: create an empty heap heapify ...
- 干货:JVM 堆内存和非堆内存
堆和非堆内存 按照官方的说法:"Java 虚拟机具有一个堆(Heap),堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建的."" ...
- 堆排序(大顶堆、小顶堆)----C语言
堆排序 之前的随笔写了栈(顺序栈.链式栈).队列(循环队列.链式队列).链表.二叉树,这次随笔来写堆 1.什么是堆? 堆是一种非线性结构,(本篇随笔主要分析堆的数组实现)可以把堆看作一个数组,也可以被 ...
- 结构之美——优先队列基本结构(四)——二叉堆、d堆、左式堆、斜堆
实现优先队列结构主要是通过堆完成,主要有:二叉堆.d堆.左式堆.斜堆.二项堆.斐波那契堆.pairing 堆等. 1. 二叉堆 1.1. 定义 完全二叉树,根最小. 存储时使用层序. 1.2. 操作 ...
随机推荐
- 51Nod 1084:矩阵取数问题 V2(多维DP)
1084 矩阵取数问题 V2 基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 一个M*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励 ...
- SSAS aggregation 的作用及其使用
作用: 聚合是为了解决查询在运行时的效率低下,在数据立方体部署的时候进行聚合,实际上是对数据立方体的预处理,方便以后查询.如若在部署时未进行聚合,则在以后每次查询时实际上都会进行一次集合的操作,等待结 ...
- 不输入密码执行sudo 命令
命令行执行的crontab 命令,但是需要包含sudo 才可以执行的命令,怎么办呢?见下: leo@leo-Ubuntu:/etc$ visudovisudo: /etc/sudoers: 权限不够v ...
- Redis源码剖析和注释(七)--- 快速列表(quicklist)
Redis 快速列表(quicklist)1. 介绍quicklist结构是在redis 3.2版本中新加的数据结构,用在列表的底层实现. 通过列表键查看一下:redis 列表键命令详解 127.0. ...
- WikiBooks/Cg Programming
https://en.wikibooks.org/wiki/Cg_Programming Basics Minimal Shader(about shaders, materials, and gam ...
- Web-Business-Application-Solution
项目地址 : https://github.com/kelin-xycs/Web-Business-Application-Solution Web-Business-Application-Sol ...
- Percona XtraDB Cluster高可用与状态快照传输(PXC 5.7 )
Percona XtraDB Cluster(下称PXC)高可用集群支持任意节点在运行期间的重启,升级或者意外宕机,即它解决了单点故障问题.那在这个意外宕机或者重启期间,该节点丢失的数据如何再次进行同 ...
- MYSQL 中的 int(11) 到底代表什么意思?
各 INT 类型无符号最大值用单位表示: INT 类型 无符号最大值用单位表示 TINYINT 255 SMALLINT 65535 MEDIUMINT 1677 万 INT 42 亿 BIGINT ...
- spring boot 学习资料
spring boot 学习资料: 学习资料 网址 Spring Boot Cookbook-极客学院 http://wiki.jikexueyuan.com/project/spring-boot- ...
- gaea-editor 知识点
github 地址:https://github.com/ascoders/gaea-editor