使用jmap命令观察JAVA堆情况

jmap(Memory Map for Java)命令用于生成堆转储快照。 如果不使用 jmap 命令,要想获取 Java 堆转储,使用 “-XX:+HeapDumpOnOutOfMemoryError” 参数,可以让虚拟机在 OOM 异常出现之后自动生成 dump 文件;Linux 命令下可以通过 kill -3 发送进程退出信号也能拿到 dump 文件。

jmap 的作用并不仅仅是为了获取 dump 文件,它还可以查询 finalizer 执行队列、Java 堆和永久代的详细信息,如空间使用率、当前使用的是哪种收集器等。

以下例子以onos程序(pid为29785)为例:

使用 -finalizerinfo 查看正等候回收的对象的信息,以下输出表示没有对象等待被finalization。

jmap -finalizerinfo pid

java如何导出堆栈日志 jmap导出堆栈_jvm

使用histo用来输出java heap对象的直方图。可以加一个live选项,用来输出live的对象。因为打印的结果太多,一下只截取部分内容

jmap -histo pid
jmap -histo:live pid

java如何导出堆栈日志 jmap导出堆栈_jvm_02

其中num是对象的编号,instances是对象的个数,bytes是对象的大小,class name是对象的class名字。

使用clstats输出类加载有关的统计信息。这里因为onos打印出来的话太多了根本截不到表头,因此以上一个死锁实验的JAVA进程为例(pid为2608)。

jam -clstats pid

java如何导出堆栈日志 jmap导出堆栈_JAVA_03

其中各列的含义如下:

  • Index - class的编号
  • Super - 父类的编号
  • InstBytes - 每个instance的bytes大小
  • KlassBytes - 该class的bytes大小
  • annotations - 注解大小
  • CpAll - 每个class中constants, tags, cache, 和 operands的大小
  • MethodCount - class中方法的个数
  • Bytecodes - byte codes的大小
  • MethodAll - method, CONSTMETHOD, stack map, 和 method data的大小
  • ROAll - 可以放到read-only memory中的class元数据的大小
  • RWAll - 可以放到read/write memory中的class元数据大小
  • Total - ROAll + RWAll
  • ClassName - class name

使用dump生成堆转储快照,dump用于dump整个java heap,dump可以接三个参数(多参数用英文逗号隔开):

  • live - dump live对象
  • format=b - 以hprof的二进制模式dump
  • file=filename - dump对象到文件中
jmap -dump:live,file=xxx.hprof pid

java如何导出堆栈日志 jmap导出堆栈_JAVA_04

java如何导出堆栈日志 jmap导出堆栈_jvm_05

因为导出的文件特别大,因此需要用到相关的工具如接下来将要实践的MAT(eclipse Memory Analyzer Tool)、Visual VM等。

jmap命令

命令格式

jmap [ option ] pid
jmap [ option ] executable core
jmap [ option ] [server-id@] remote-hostname-or-IP

参数说明

1)options:

executable:Java executable from which the core dump was produced.

(可能是产生core dump的java可执行程序)

core:将被打印信息的core dump文件

remote-hostname-or-IP:远程debug服务的主机名或ip

server-id:唯一id,假如一台主机上多个远程debug服务

2)基本参数:

-dump:[live,]format=b,file= 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件. -finalizerinfo 打印正等候回收的对象的信息.

-heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.

-histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.

-permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来.

-F 强迫.在pid没有相应的时候使用-dump或者-histo参数. 在这个模式下,live子参数无效.

-h | -help 打印辅助信息

-J 传递参数给jmap启动的jvm.

3)pid

pid 需要被打印配置信息的java进程id,可以用jps查询.

jmap使用错误以及解决方法

1、java进程禁止在运行中时被用户访问内存和状态

使用jmap可能会出现以下错误:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9p1ikIa2-1610593187176)(/home/lxj/.config/Typora/typora-user-images/1610508002017.png)]

这是因为ptrace-scope为了防止用户访问当前正在运行的进程的内存和状态 , 默认情况下不允许再访问了.

临时开启(/proc/sys/kernel/yama/ptrace_scope中的内容默认为1,0:允许, 1:不允许):

echo 0 > /proc/sys/kernel/yama/ptrace_scope

永久开启:

/etc/sysctl.d/10-ptrace.conf

添加或修改为以下这一句:

kernel.yama.ptrace_scope = 0