【Java进阶营】虚拟机研究系列-Java各种类型对象占用内存情况分析(下)

本文深入探讨了Java中枚举、ArrayList和HashMap对象在内存中的占用情况。基于HotSpot JVM, JDK1.8, 64位机器,开启指针压缩的环境,分析了对象头、实例数据、枚举类、ArrayList和HashMap的构造、存储和内存占用。文章指出,了解这些细节有助于优化内存使用和提升性能。" 112375162,10536465,Django + Nuxt 全栈美食分享:快速实现REST API与前端首页,"['Django', '前端开发', 'RESTful API', 'Nuxt框架']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前提回顾

建议大家从[【Java技术专题-JVM研究系列(39)Java各种类型对象占用内存情况分析(上)】]开始学习比较好,这样子会有一个承接和过度。根据前面的学习的内存占用计算规则,可以计算出一个对象在内存中的占用空间大小情况,下面举例分析下Java中的Enum, ArrayList及HashMap的内存占用情况,读者可以仿照分析计算过程来计算其他数据结构的内存占用情况

注: 下面的分析计算基于HotSpot Jvm, JDK1.8, 64位机器,开启指针压缩。

对象头

这里只关注其内存占用大小。在64位机器上,默认不开启指针压缩(-XX:-UseCompressedOops)的情况下,对象头占用12bytes,开启指针压缩(-XX:+UseCompressedOops)则占用16bytes。

实例数据:

对象引用(reference)类型在64位机器上,关闭指针压缩时占用8bytes, 开启时占用4bytes,一般指的是局部变量表或者操作数栈中的reference类型或者针对于成员变量情况下的地址引用(shallow size)

注: 下面的分析计算基于HotSpot Jvm, JDK1.8, 64位机器,开启指针压缩

枚举类

创建enum时,编译器会生成一个相关的类,这个类继承自java.lang.Enum。Enum类拥有两个属性变量,分别为int的ordinal和String的name, 相关源码如下:

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
    /**
     * The name of this enum constant, as declared in the enum declaration.
     * Most programmers should use the {@link #toString} method rather than
     * accessing this field.
     */
    private final String name;

    /**
     * The ordinal of this enumeration constant (its position
     * in the enum declaration, where the initial constant is assigned
     * an ordinal of zero).
     *
     * Most programmers will have no use for this field.  It is designed
     * for use by sophisticated enum-based data structures, such as
     * {@link java.util.EnumSet} and {@link java.util.EnumMap}.
     */
    private final int ordinal;
}

以下面的TestEnum为例进行枚举类的内存占用分析

public enum TestEnum {
        ONE(1, "one"),
        TWO(2, "two");

        private int code;
        private String desc;

        TestEnum(int code, String desc) {
            this.code = code;
            this.desc = desc;
        }

        public int getCode() {
            return code;
        }

        public String getDesc() {
            return desc;
        }
}

这里TestEnum的每个实例除了父类的两个属性外,还拥有一个int的code及String的desc属性,所以一个TestEnum的实例本身所占用的内存大小为:

12(header) + 4(ordinal) + 4(name reference) + 4(code) + 4(desc reference) = 28(padding) -> 32 bytes.

总共占用的内存大小为:

按照上面对字符串类型的分析,desc和name都占用:48bytes。
所以TestEnum.ONE占用总内存大小为:

12(header) + 4(ordinal) + 4(code) + 48 * 2(desc, name) + 4(desc reference) + 4(name reference) = 128 (bytes)

ArrayList

ArrayList实现List接口,底层使用数组保存所有元素。其操作基本上是对数组的操作。下面分析下源代码:

底层使用数组保存数据:

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     */
    transient Object[] elementData; // non-private to simplify nested class access

构造方法

ArrayList提供了三种方式的构造器,可以构造一个默认的空列表、构造一个指定初始容量的空列表及构造一个包含指定collection元素的列表,这些元素按照该collection的迭代器返回它们的顺序排列

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    /**
     * Constructs an empty l
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值