专栏首页墨白的Java基地JVM优化系列-------[4丶jmap的使用以及内存溢出分析]

JVM优化系列-------[4丶jmap的使用以及内存溢出分析]

正文

引言

前面几章内容我们学习了JVM的内存回收和JVM参数等系列,今天墨白给大家分享的是jmap的使用以及内存溢出分析等详情,话不多说,正文开始;

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

在写这篇文章的时候我发现了一个问题,新版的Linux系统加入了 ptrace-scope 机制. 这种机制为了防止用户访问当前正在运行的进程的内存和状态, 而一些调试软件本身就是利用 ptrace 来进行获取某进程的内存状态的(包括GDB),所以在新版本的Linux系统, 默认情况下不允许再访问了,所以我们无法使用之前的jmap -heap这个命令了,今天我们用-clstats这个命令来查看JVM内存分析;

先查看下jmap的命令:

    Example: jmap -dump:live,format=b,file=heap.bin 
[root@localhost ~]# jmap -h
Usage:
== 连接到运行进程并打印类加载器统计信息
    jmap -clstats 
        to connect to running process and print class loader statistics
== 连接到正在运行的进程并打印有关等待完成的对象的信息
    jmap -finalizerinfo 
        to connect to running process and print information on objects awaiting finalization
== 连接到运行进程并打印Java对象堆的直方图  
    jmap -histo[:live] 
        to connect to running process and print histogram of java object heap
        if the "live" suboption is specified, only count live objects
== 连接到正在运行的进程并转储Java堆
    jmap -dump: 
        to connect to running process and dump java heap
    dump-options:
      live         dump only live objects; if not specified,
                   all objects in the heap are dumped.
      format=b     binary format
      file=  dump heap to 
    Example: jmap -dump:live,format=b,file=heap.bin 
  • 查看内存使用情况我们就用-clstats这个命令
== 连接到运行进程并打印类加载器统计信息
[root@localhost bin]# jmap -clstats 30685
==================================省略3600条信息=================================
         0        536          56    3584           9       449      2304    2024     4768     6792 websocket.snake.SnakeAnnotation
             13578248    2340680       15712 7693904       40079   1987618  11822808 7659360 15423064 23082424 Total
                58.8%      10.1%        0.1%   33.3%           -      8.6%     51.2%   33.2%    66.8%   100.0%
Index Super InstBytes KlassBytes annotations   CpAll MethodCount Bytecodes MethodAll   ROAll    RWAll    Total ClassName

细心找找我们发现它有几个关键字,如下

  • Configuration:堆内存配置信息
  • Usage:堆内存的使用情况
  • PS Young Generation :年轻代
  • PS Old Generation :年老代

查看内存中对象数量及大小,如下:

 1== 查看所有对象,包括活跃以及非活跃的
 2[root@localhost ~]# jmap -histo 30685 | more
 3 num     #instances         #bytes  class name (module)
 4-------------------------------------------------------
 5   1:         60386        5335640  [B (java.base@9.0.4)
 6   2:          1220        3146456  [C (java.base@9.0.4)
 7   3:         42784        1026816  java.lang.String (java.base@9.0.4)
 8   4:         19972         639104  java.util.HashMap$Node (java.base@9.0.4)
 9   5:          5436         627008  [I (java.base@9.0.4)
10   6:          3824         462160  java.lang.Class (java.base@9.0.4)
11===============================忽略内容=======================================
12  41:           632          25280  java.util.LinkedHashMap$Entry (java.base@9.0.4)

对象说明:

== 对象说明
B byte
C char
D double
F float
I int
J long
Z boolean
[ 数组,如[I表示int[]
[L+类名 其他对象
  • 我们还可以将内存使用情况dump到文件中:

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

==  将内存使用的详细情况输出到文件
[root@localhost test]#  jmap -dump:format=b,file=m.dat 30685 
Heap dump file created
[root@localhost test]# ll
总用量 31752
drwxr-xr-x. 2 root root        6 10月 11 00:25 aaa
== 可以看到新建了一个m.dat的文件
-rw-------. 1 root root 32505476 10月 11 00:30 m.dat
-rw-r--r--. 1 root root      575 10月  8 23:58 TestJVM.class
-rw-r--r--. 1 root root      225 10月  8 23:58 TestJVM.java
  • 通过jhat对dump文件进行分析;

我们将jvm的内存dump到文件中,这个文件是一个二进制的文件,不方便查看,这时我们可以借助于jhat工具进行查看。需要注意一点的是,Java9版本之后就没有jhat命令了;

== 通过jhat对dump文件进行分析
[root@node01 test]# jhat ‐port 9999 m.dat
Reading from /test/m.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/

这里面的内容就是jhat做的解析内容,可以看到它打包方式有一些是数组,如数组的对象有那些内容,还可以看到打包是以Javax.el方式又有一些,还有servlet等方式,它会以一些包的方式自动给我们分类,这些方法也可以点击进去查看详情.包括实例等等有很多内容,这里就不一一说了,感兴趣的小伙伴可以看一下,最后面还给我们提供了OQL查询功能;

这个功能类似SQL语句,下面我们看下是怎么使用的,它有给我们提供API,点击QQL Help就可以查看它的使用文档了;

现在我们自己来玩一下这个功能,查询一个字符串大于100的内容有哪些;

本文分享自微信公众号 - 框架师(mohu121)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何写出让同事无法维护的代码?

    原文:http://mindprod.com/jgloss/unmain.html

    Rocky0429
  • 优雅的使用 ThreadLocal

    在我们日常 Web 开发中难免遇到需要把一个参数层层的传递到最内层,然后中间层根本不需要使用这个参数,或者是仅仅在特定的工具类中使用,这样我们完全没有必要在每一...

    Java技术江湖
  • 我是一个Java类(必看,附带精彩吐槽)

    大家好,我是一个Java类,很高兴能向大家介绍一下我的前世今生。要知道,自从面向对象这种编程思想横空出世以来,它变得越来越受欢迎,而类这个概念又在其中扮演了非常...

    Java技术江湖
  • HashMap 和Hashtable的区别

    HashMap与Hashtable的区别是面试中经常遇到的一个问题。这个问题看似简单,但如果深究进去,也能了解到不少知识。本文对两者从来源,特性,算法等多个方面...

    Java技术江湖
  • 使用Joda-Time优雅的处理日期时间

    在Java中处理日期和时间是很常见的需求,基础的工具类就是我们熟悉的Date和Calendar,然而这些工具类的api使用并不是很方便和强大,于是就诞生了Jod...

    哲洛不闹
  • 求你了,再问你Java内存模型的时候别再给我讲堆栈方法区了…

    最近,面试过很多Java中高级开发,问过很多次关于Java内存模型的知识,问完之后,很多人上来就开始回答:

    Java技术江湖
  • 深入浅出Java中的clone克隆方法,写得太棒了!

    clone 顾名思义就是 复制 , 在Java语言中, clone方法被对象调用,所以会复制对象。所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空...

    Java技术江湖
  • Java注解(Annotation):请不要小看我!

    网络上对注解的解释过于严肃、刻板,这并不是我喜欢的风格。尽管这样的解释听起来非常的专业。

    Java技术江湖
  • 用不用lambda,这是一个问题

    Sun在2009年开启了代号为“dolphin”的工程,计划在JDK1.7中加入lambda表达式、虚拟机模块化支持、动态语言支持等新特性。但是由于深陷商业竞争...

    Java技术江湖
  • Java是如何实现平台无关性(跨平台)的?

    相信对于很多Java开发来说,在刚刚接触Java语言的时候,就听说过Java是一门跨平台的语言,Java是平台无关性的,这也是Java语言可以迅速崛起并风光无限...

    Java技术江湖

扫码关注云+社区

领取腾讯云代金券