java如何实现打印list对象占用多大内存

 更新时间:2025年07月18日 08:56:19   作者:慧一居士  
在 Java 中精确计算 List 对象占用的内存大小需要考虑对象头,引用,数组开销和元素对象本身的大小,下面小编就来和大家详细介绍一下具体实现方式吧

在 Java 中精确计算 List 对象占用的内存大小需要考虑对象头、引用、数组开销和元素对象本身的大小。以下是几种实现方式:

方法 1:使用 Java Object Layout (JOL) 工具(推荐)

JOL 是 OpenJDK 提供的官方工具,可精确分析对象内存布局。

步骤:

添加 Maven 依赖

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.17</version> <!-- 检查最新版本 -->
</dependency>

打印内存占用

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.info.GraphLayout;
import java.util.ArrayList;
import java.util.List;

public class ListMemorySize {
    public static void main(String[] args) {
        // 创建并填充 List
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            list.add("Hello" + i); // 添加100个字符串
        }

        // 1. 打印 List 对象本身的大小(不包括元素)
        System.out.println("List 对象本身大小:");
        System.out.println(ClassLayout.parseInstance(list).toPrintable());

        // 2. 打印整个 List 结构的总大小(包括元素)
        long totalSize = GraphLayout.parseInstance(list).totalSize();
        System.out.println("List + 所有元素总内存: " + totalSize + " bytes");
    }
}

输出示例:

List 对象本身大小:
ArrayList instance internals:
OFF  SZ     TYPE DESCRIPTION               VALUE
  0   8          (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4          (object header: class)    0x000012c0
 12   4      int AbstractList.modCount     100
 16   4      int ArrayList.size            100
 20   4      Object[] ArrayList.elementData (object)
Instance size: 24 bytes

List + 所有元素总内存: 4160 bytes

方法 2:手动估算(仅参考)

对于 ArrayList

1.ArrayList 对象本身

  • 对象头:12 bytes(64位 JVM 开启压缩指针时)
  • int modCountint size:各 4 bytes
  • Object[] elementData 引用:4 bytes
  • 总计 ≈ 24 bytes

2.底层数组 Object[]

  • 数组对象头:16 bytes
  • 数组长度:4 bytes
  • 每个引用:4 bytes × 数组容量(如默认容量 10)
  • 总计 = 16 + 4 + (4 × capacity)

3.元素对象

每个元素对象的实际大小(如 String 对象约 24-48 bytes)

方法 3:使用Instrumentation(需 Java Agent)

适用于需要精确计算的场景,但配置较复杂。

创建 Agent 类

import java.lang.instrument.Instrumentation;

public class MemoryAgent {
    private static Instrumentation instrumentation;

    public static void premain(String args, Instrumentation inst) {
        instrumentation = inst;
    }

    public static long getObjectSize(Object o) {
        return instrumentation.getObjectSize(o);
    }
}

在 MANIFEST.MF 中声明

Premain-Class: MemoryAgent

计算大小

public class Main {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        // 添加元素...

        // 仅计算 List 本身(不包括元素)
        long size = MemoryAgent.getObjectSize(list);
        System.out.println("List size: " + size + " bytes");
    }
}

关键注意事项

1.JVM 差异

  • 对象头大小(通常 8-16 bytes)
  • 是否开启压缩指针(-XX:+UseCompressedOops
  • 内存对齐(通常按 8 bytes 对齐)

2.包含元素

  • ClassLayout 只分析对象本身
  • GraphLayout 会递归计算所有引用对象

3.常见 List 实现

  • ArrayList:底层是数组,预分配空间可能大于实际元素数
  • LinkedList:每个元素含前后指针,开销更大

总结建议

  • 快速查看内存:使用 JOLGraphLayout.parseInstance(list).totalSize()
  • 生产环境监控:使用 JVM 工具(如 VisualVM、JProfiler)
  • 精确测量:结合 Instrumentation 和 JOL

重要:Java 中对象内存占用是近似值,不同 JVM 实现和垃圾回收器会导致结果差异。

到此这篇关于java如何实现打印list对象占用多大内存的文章就介绍到这了,更多相关java打印list对象占用内存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 15个高级Java多线程面试题及回答

    15个高级Java多线程面试题及回答

    这篇文章主要介绍了15个高级Java多线程面试题及回答,翻译自国外的一篇文章,这些面试题容易混淆、较难回答,需要的朋友可以参考下吧
    2014-05-05
  • Java内部类持有外部类导致内存泄露的原因与解决方案详解

    Java内部类持有外部类导致内存泄露的原因与解决方案详解

    这篇文章主要为大家详细介绍了Java因为内部类持有外部类导致内存泄露的原因以及其解决方案,文中的示例代码讲解详细,希望对大家有所帮助
    2022-11-11
  • SpringBoot 整合 ShardingSphere4.1.1实现分库分表功能

    SpringBoot 整合 ShardingSphere4.1.1实现分库分表功能

    ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成,本文给大家介绍SpringBoot 整合 ShardingSphere4.1.1实现分库分表,感兴趣的朋友一起看看吧
    2023-12-12
  • 在IDEA中如何设置最多显示文件标签个数

    在IDEA中如何设置最多显示文件标签个数

    在使用IDEA进行编程时,可能会同时打开多个文件,当文件过多时,文件标签会占据大部分的IDEA界面,影响我们的编程效率,因此,我们可以通过设置IDEA的文件标签显示个数,来优化我们的编程环境,具体的设置方法如下
    2024-10-10
  • Spring Boot利用@Async异步调用:ThreadPoolTaskScheduler线程池的优雅关闭详解

    Spring Boot利用@Async异步调用:ThreadPoolTaskScheduler线程池的优雅关闭详解

    这篇文章主要给大家介绍了关于Spring Boot利用@Async异步调用:ThreadPoolTaskScheduler线程池的优雅关闭的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-05-05
  • Netty通道的容器属性Attribute详解

    Netty通道的容器属性Attribute详解

    这篇文章主要介绍了Netty通道的容器属性Attribute详解,Netty中的Channel通道类,有类似于Map的容器功能,可以通过键值对的形式来保存任何Java Object的值,一般来说可以存放一些与通道实例相关联的属性,比如说服务期端的ServerSession会话实例,需要的朋友可以参考下
    2023-12-12
  • Java Chassis3注册中心分区隔离技术解密

    Java Chassis3注册中心分区隔离技术解密

    这篇文章主要为大家介绍了Java Chassis3注册中心分区隔离技术解密,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • Java实现简易的分词器功能

    Java实现简易的分词器功能

    搜索功能是具备数据库功能的系统的一大重要特性和功能,生活中常见的搜索功能基本上都具备了分词搜索功能.然而ES功能固然强大,但对于学生或小项目而言整合起来太费人力物力,若是写个分词器就会使项目锦上添花,使其不仅仅是只能单关键词搜索的系统,需要的朋友可以参考下
    2021-06-06
  • 详解Spring boot使用Redis集群替换mybatis二级缓存

    详解Spring boot使用Redis集群替换mybatis二级缓存

    本篇文章主要介绍了详解Spring boot使用Redis集群替换mybatis二级缓存,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • java15新功能的详细讲解

    java15新功能的详细讲解

    这篇文章主要介绍了java15的新功能,虽然java15并不是长期支持的版本,但是很多新功能还是很有用的。感兴趣的小伙伴可以参考一下
    2021-08-08

最新评论