jmap命令详解:内存分析利器

一、jmap介绍

jmap是JDK自带的一款用于获取Java应用的heap或类信息快照的命令行工具,它能够让我们更好地了解内存中对象的使用情况,从而方便优化应用程序。

二、jmap常用选项

jmap有多个选项,我们通常会用到以下几个:

-heap

该选项可以让我们获得应用程序的heap大小、占用率等内存信息。例如:

jmap -heap 19321

这条命令会输出进程号19321对应的Java应用的heap信息,例如:

Attaching to process ID 19321, please wait...
Debugger attached successfully.
Server compiler detected
JVM version is 25.102-b14
using thread-local object allocation.
Parallel GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 2147483648 (2048.0MB)  // 最大可用heap大小
   NewSize          = 1048576 (1.0MB)        // 新生代大小
   MaxNewSize       = 33554432 (32.0MB)      // 新生代最大大小
   OldSize          = 4194304 (4.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 = 279183360 (266.125MB)  // Eden区域容量
   used     = 36645336 (34.925048828125MB)  // 已使用空间
   free     = 242538024 (231.199951171875MB)  // 未使用空间
   13.11123171556415% used //空间使用率
...

-histo[:live]

该选项会输出Java堆内存中的对象信息,包括对象的数量、占用内存大小、类名等。如果加上”:live”参数,则只统计存活对象的信息。例如:

jmap -histo 19321

这条命令会输出进程号19321对应的Java应用中对象的统计信息,例如:

num     #instances         #bytes  class name
----------------------------------------------
   1:        183765     474534880  [C  // char数组对象
   2:          8749     274628312  [B  // byte数组对象
   3:         21869     164735880  java.lang.String
   4:          9350      57402584  [I  // int数组对象
   5:        310942      49910872  java.util.LinkedHashMap$Entry
   ...

-dump:[live,]format=b,file=filename

该选项可以生成一个Java堆的dump文件,我们可以用jhat、MAT等工具来解析这个文件,进行一些内存分析。例如:

jmap -dump:live,format=b,file=heapdump.bin 19321

这条命令会生成进程号19321对应Java应用的存活对象的dump文件heapdump.bin。我们可以使用jhat工具来解析这个文件:

jhat heapdump.bin

然后在浏览器中访问http://localhost:7000/即可查看内存分析报告。

三、jmap的优化实践

1. 分析内存泄漏

使用jmap可以针对Java应用程序进行内存泄漏分析。如果应用程序出现了内存泄漏,就可以借助jmap管理Java堆中的对象,通过GC日志、堆转储文件等方式来确定内存泄漏的类型和原因。

下面是一个jmap分析内存泄漏的示例代码:

public class MemoryLeak {

    private static List list = new LinkedList();

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 100000; i++) {
            list.add(new Object());
        }
        Thread.sleep(30000);
        list.clear();
        System.out.println("list size: " + list.size());
    }

}

在运行该程序之后,我们可以使用如下命令来获取Java进程的pid:

jps -l

得到pid之后,我们可以使用如下命令来生成堆转储文件:

jmap -dump:live,format=b,file=heapdump.bin pid

使用MAT等工具,可以分析堆转储文件,找到内存泄漏的对象。例如,我们可以在MAT的Histogram视图中查看对象数量排名前100的对象,如下图所示:

可以看到,LinkedList$Entry对象数量排名第一,说明LinkedList中的节点占用了大量的内存。打开该对象的histogram视图,可以查看该对象的实例数量、大小、引用关系等信息,如下图所示:

可以看到,可以直接从该对象的链表、size属性追寻到具体的对象,从而找到内存泄漏的原因。

2. 分析OOM

jmap可以用于定位一个Java进程的OOM问题,步骤与上面类似。首先,需要在发生OOM的时候,使用jmap生成一个堆映射文件。这个文件可以与MAT等工具一起使用,从而进行内存分析。

下面是OOM的一些示例代码:

public class OOMTest {

    private static List list = new LinkedList();

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 10_000_000; i++) {
            list.add(new Object());
            if (i % 1000 == 0) {
                System.out.println("add object: " + i);
            }
        }
    }

}

在运行该程序之后,我们可以使用如下命令来获取Java进程的pid:

jps -l

得到pid之后,我们可以使用如下命令来生成堆转储文件:

jmap -dump:live,format=b,file=heapdump.bin pid

使用MAT等工具,可以分析堆转储文件,找到OOM的原因。例如,我们可以在MAT的Histogram视图中查看对象数量排名前10的对象,如下图所示:

可以看到,Object实例的数量是最多的,Java应用在运行过程中创建了非常多的Object实例,使得堆内存被耗尽,从而发生了OOM。

四、jmap小结

jmap是一个非常强大的工具,可以帮助我们更好地了解Java应用程序的内存使用情况,从而进行优化。在实践中,我们可以使用jmap分析内存泄漏、OOM等问题,从而根据分析结果对应用程序进行优化。

原创文章,作者:KTDSR,如若转载,请注明出处:https://www.506064.com/n/369467.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
KTDSR的头像KTDSR
上一篇 2025-04-12 13:01
下一篇 2025-04-13 11:45

相关推荐

  • Python创建分配内存的方法

    在python中,我们常常需要创建并分配内存来存储数据。不同的类型和数据结构可能需要不同的方法来分配内存。本文将从多个方面介绍Python创建分配内存的方法,包括列表、元组、字典、…

    编程 2025-04-29
  • lsw2u1:全能编程开发工程师的利器

    lsw2u1是一款多功能工具,可以为全能编程开发工程师提供便利的支持。本文将从多个方面对lsw2u1做详细阐述,并给出对应代码示例。 一、快速存取代码段 在日常开发中,我们总会使用…

    编程 2025-04-29
  • Python刷课:优化学习体验的利器

    Python刷课作为一种利用自动化技术优化学习体验的工具已经被广泛应用。它可以帮助用户自动登录、自动答题等,让用户在学习过程中可以更加专注于知识本身,提高效率,增加学习乐趣。 一、…

    编程 2025-04-29
  • Python命令大全及说明

    Python是一种高级编程语言,由Guido van Rossum于1989年底发明。它具有良好的语法结构和面向对象的编程思想,具有简洁、易读、易学的特点,是初学者以及专业开发人员…

    编程 2025-04-29
  • Python变量在内存中的存储

    该文章将从多个方面对Python变量在内存中的存储进行详细阐述,包括变量的声明和赋值、变量的引用和指向、内存地址的变化、内存管理机制等。 一、声明和赋值 在Python中,变量声明…

    编程 2025-04-29
  • Git config命令用法介绍:用正确的邮箱保障开发工作

    本文将详细介绍如何使用git config命令配置Git的全局和本地用户信息,特别是如何正确使用用户邮箱,保障Git操作的正常进行。 一、git config命令介绍 Git中的每…

    编程 2025-04-29
  • Python SSH 远程执行命令

    Python SSH 远程执行命令是指在一个服务器上执行远程另一个服务器上命令。如果你需要在本地机器上执行命令,或者在远程机器上执行本地命令,你都可以使用 SSH。在 Python…

    编程 2025-04-29
  • Python计算内存占用

    Python是一种高级的、解释性的、面向对象的、动态的程序语言,因其易于学习、易于阅读、可移植性好等优点,越来越受到开发者的青睐。当我们编写Python代码时,可能经常需要计算程序…

    编程 2025-04-28
  • 使用Go-Redis获取Redis集群内存使用率

    本文旨在介绍如何使用Go-Redis获取Redis集群的内存使用率。 一、Go-Redis简介 Go-Redis是一个用于连接Redis服务器的Golang客户端。它支持Redis…

    编程 2025-04-28
  • 剖析命令执行函数

    在编程开发过程中,命令执行函数是非常常见的一个概念。它是指接受一个命令字符串,并将其解析执行,返回相应的结果或错误信息的函数。本文将从多个方面对命令执行函数进行详细的阐述,包括其定…

    编程 2025-04-28

发表回复

登录后才能评论