前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jmap及内存溢出分析

jmap及内存溢出分析

作者头像
乐心湖
发布2021-01-18 14:45:29
1.8K0
发布2021-01-18 14:45:29
举报
文章被收录于专栏:MyTechnology

前面通过jstat可以对jvm堆的内存进行统计分析,而 jmap 可以获取到更加详细的内容,如:内存使用情况的汇总、对内存溢出的定位与分析。

查看内存使用情况

代码语言:javascript
复制
jmap -heap 6219

Attaching to process ID 6219, please wait...
Debugger attached successfully. 
Server compiler detected. 
JVM version is 25.141-b15 

using thread-local object allocation. 
Parallel GC with 2 thread(s) 

Heap Configuration: #堆内存配置信息 
    MinHeapFreeRatio = 0 
    MaxHeapFreeRatio = 100 
    MaxHeapSize = 488636416 (466.0MB) 
    NewSize = 10485760 (10.0MB) 
    MaxNewSize = 162529280 (155.0MB) 
    OldSize = 20971520 (20.0MB) 
    NewRatio = 2 
    SurvivorRatio = 8 
    MetaspaceSize = 21807104 (20.796875MB) 
    CompressedClassSpaceSize = 1073741824 (1024.0MB) 
    MaxMetaspaceSize = 17592186044415 MB 
    G1HeapRegionSize = 0 (0.0MB) 

Heap Usage: # 堆内存的使用情况 
PS Young Generation #年轻代 
Eden Space: 
    capacity = 123731968 (118.0MB) 
    used = 1384736 (1.320587158203125MB) 
    free = 122347232 (116.67941284179688MB) 
    1.1191416594941737% used 
From Space: 
    capacity = 9437184 (9.0MB) 
    used = 0 (0.0MB) 
    free = 9437184 (9.0MB) 
    0.0% used 
To Space: 
    capacity = 9437184 (9.0MB) 
    used = 0 (0.0MB) 
    free = 9437184 (9.0MB) 
    0.0% used 
PS Old Generation #年老代 
    capacity = 28311552 (27.0MB) 
    used = 13698672 (13.064071655273438MB) 
    free = 14612880 (13.935928344726562MB) 
    48.38545057508681% used 

13648 interned Strings occupying 1866368 bytes.

查看内存中对象数量及大小

代码语言:javascript
复制
#查看所有对象,包括活跃以及非活跃的 
jmap -histo <pid> | more
#查看活跃对象
jmap -histo:live <pid> | more

对象说明:

  • B byte
  • C char
  • D double
  • F float
  • I int
  • J long
  • Z boolean
  • [ 数组,如 [I 表示 int[]
  • [L+类名 其他对象

将内存使用情况dump到文件中

有些时候我们需要将jvm当前内存中的情况dump到文件中,然后对它进行分析,jmap也是支持dump到文件中的。

代码语言:javascript
复制
#用法: 
jmap -dump:format=b,file=dumpFileName <pid> 
#示例 
jmap -dump:format=b,file=/tmp/dump.dat 6219

可以看到已经在/tmp下生成了dump.dat的文件

通过jhat对dump文件进行分析

上面我们将 jvm 的内存信息 dump 到文件中,这个文件是一个二进制的文件,不方便查看,这时我们可以借助于 jhat 工具进行查看。

代码语言:javascript
复制
#用法: 
jhat -port <port> <file> 

#示例: 
jhat -port 9999 /tmp/dump.dat 
Reading from /tmp/dump.dat... 
Dump file created Mon Sep 10 01:04:21 CST 2018 
Snapshot read, resolving... 
Resolving 204094 objects... 
Chasing references, expect 40 dots........................................ 
Eliminating duplicate references........................................ 
Snapshot resolved. 
Started HTTP server on port 9999 
Server is ready

打开浏览器进行访问:http://ip:9999/

通过MAT工具对dump文件进行

MAT(Memory Analyzer Tool),一个基于Eclipse的内存分析工具,是一个快速、功能丰富的JAVA heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。使用内存分析工具从众多的对象中进行分析,快速的计算出在内存中对象的占用大小,看看是谁阻止了垃圾收集器的回收工作,并可以通过报表直观的查看到可能造成这种结果的对象。

官网地址:https://www.eclipse.org/mat/

官方下载:https://www.eclipse.org/mat/downloads.php

蓝奏云:https://www.lanzoux.com/ixMEUg9oskh

将下载得到的MemoryAnalyzer-1.8.0.20180604-win32.win32.x86_64.zip进行解压:

查看对象以及它的依赖:

查看可能存在内存泄露的分析:

内存溢出的定位与分析

内存溢出在实际的生产环境中经常会遇到,比如,不断的将数据写入到一个集合中,出现了死循环,读取超大的文

件等等,都可能会造成内存溢出。如果出现了内存溢出,首先我们需要定位到发生内存溢出的环节,并且进行分析,是正常还是非正常情况,如果是正常的需求,就应该考虑加大内存的设置,如果是非正常需求,那么就要对代码进行修改,修复这个bug。

首先,我们得先学会如何定位问题,然后再进行分析。如何定位问题呢,我们需要借助于jmap与MAT工具进行定位分析。

接下来,我们模拟内存溢出的场景。

编写代码,向List集合中添加100万个字符串,每个字符串由1000个UUID组成。如果程序能够正常执行,最后打印ok。

代码语言:javascript
复制
/**
 * 模拟内存溢出
 */
public class TestJvmOutOfMemory {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<>();
        for (int i = 0; i < 10000000; i++) {
            StringBuilder str = new StringBuilder();
            for (int j = 0; j < 1000; j++) {
                str.append(UUID.randomUUID().toString());
            }
            list.add(str.toString());
        }
        System.out.println("OK");
    }
}

为了演示效果,我们将设置执行的参数,这里使用的是Idea编辑器。

-Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

结果:

代码语言:javascript
复制
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOfRange(Arrays.java:3664)
    at java.lang.String.<init>(String.java:207)
    at java.lang.StringBuilder.toString(StringBuilder.java:407)
    at com.xn2001.jvm.TestJvmOutOfMemory.main(TestJvmOutOfMemory.java:18)

可以看到,当发生内存溢出时,会dump文件到java_pid5348.hprof。

导入到MAT工具中进行分析

可以看到,有91.03%的内存由Object[]数组占有,所以比较可疑。

分析:这个可疑是正确的,因为已经有超过90%的内存都被它占有,这是非常有可能出现内存溢出的。

查看详情:

可以看到集合中存储了大量的uuid字符串。


本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 查看内存使用情况
  • 查看内存中对象数量及大小
  • 将内存使用情况dump到文件中
  • 通过jhat对dump文件进行分析
  • 通过MAT工具对dump文件进行
  • 内存溢出的定位与分析
相关产品与服务
腾讯云 BI
腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档