1. 概述

本文将深入探讨 boolean 类型在 JVM 中的内存占用情况。你可能以为 boolean 只占 1 bit?别急,真相没那么简单。

我们将借助 JOL(Java Object Layout)工具直观测量对象内存布局,并剖析背后的设计原理——包括对象头、字段对齐、压缩指针等影响因素。目标是搞清楚:一个 boolean 到底占多少字节?数组呢?为什么?

✅ 本文适合有一定 JVM 基础的开发者,避免“int 是 4 字节”这类基础科普。


2. 环境准备

要分析 JVM 内存布局,首选工具是 JOL(Java Object Layout),它能精确打印对象在堆中的结构。

引入依赖:

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.10</version>
</dependency>

之后就可以通过 ClassLayout.parseClass()ClassLayout.parseInstance() 查看类或实例的内存分布。


3. 基本类型内存占用

先看看 JVM 对基本类型的底层支持情况:

System.out.println(VM.current().details());

在默认开启压缩指针(Compressed Oops)的 64 位 JVM 中,输出如下:

# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

关键信息提炼:

  • boolean / byte:1 字节
  • char / short:2 字节
  • int / float:4 字节
  • long / double:8 字节
  • ✅ 引用类型(reference):4 字节(压缩后)
  • ✅ 数组元素大小与字段一致

⚠️ 注意:每个 boolean 占 1 字节(8 bit),不是 1 bit!

3.1 关闭压缩指针的影响

即使通过 -XX:-UseCompressedOops 关闭压缩指针,boolean 大小依然不变:

# Field sizes by type: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

可以看到,引用类型从 4 字节变为 8 字节,但 boolean 仍是 1 字节。

❌ 所以别再幻想“用 boolean 节省内存”了——它根本不按 bit 存。

3.2 为什么不是 1 bit?防止 Word Tearing

你可能会问:为什么不用一个 bit 来存 boolean?

根本原因在于 原子性与地址访问限制

现代 CPU 通常以字(word)为单位进行内存访问,无法原子操作单个 bit。如果多个 boolean 共享一个字节,修改其中一个 bit 可能会“误伤”邻近 bit,这种现象叫 Word Tearing

JVM 明确禁止 Word Tearing(参考 JLS 17.6),要求每个字段/数组元素独立可寻址。

✅ 因此,JVM 选择用 1 字节存储 boolean,牺牲空间换安全和一致性。


4. 对象中的 boolean 字段内存布局

来看一个简单类:

class BooleanWrapper {
    private boolean value;
}

使用 JOL 查看其内存布局:

System.out.println(ClassLayout.parseClass(BooleanWrapper.class).toPrintable());

输出:

 OFFSET  SIZE      TYPE DESCRIPTION                               VALUE
      0    12           (object header)                           N/A
     12     1   boolean BooleanWrapper.value                      N/A
     13     3           (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

结构拆解:

  • 12 字节对象头
    • 两个 mark word:存 GC 标记、锁状态、hashCode
    • 一个 klass word:指向类元数据(runtime type info)
  • 1 字节boolean value 字段
  • 3 字节填充(padding):用于对象对齐

对齐规则说明

JVM 默认要求对象大小为 8 字节对齐。当前总大小为 13 字节(12 + 1),需补 3 字节凑成 16。

⚠️ 这意味着:即使字段只占 1 字节,也可能因对齐浪费 3 字节。

4.1 自定义对齐的影响

通过 -XX:ObjectAlignmentInBytes=32 将对齐改为 32 字节:

OFFSET  SIZE      TYPE DESCRIPTION                               VALUE
      0    12           (object header)                           N/A
     12     1   boolean BooleanWrapper.value                      N/A
     13    19           (loss due to the next object alignment)
Instance size: 32 bytes

此时填充变为 19 字节,总大小 32 字节。

✅ 大对齐会显著增加内存开销,通常只在特定场景(如堆外内存)使用。


5. boolean 数组的内存布局

再看数组的情况:

boolean[] value = new boolean[3];
System.out.println(ClassLayout.parseInstance(value).toPrintable());

输出:

OFFSET  SIZE      TYPE DESCRIPTION                              
      0     4           (object header)  # mark word
      4     4           (object header)  # mark word
      8     4           (object header)  # klass word
     12     4           (object header)  # array length
     16     3   boolean [Z.<elements>    # [Z means boolean array                        
     19     5           (loss due to the next object alignment)

结构分析:

  • 16 字节对象头
    • 3 个 header 字(mark、klass)共 12 字节
    • 额外 4 字节存数组长度array length),这是数组特有的
  • 3 字节数据区:3 个 boolean 元素,各占 1 字节
  • 5 字节填充:使总大小对齐到 8 字节倍数(16 + 3 + 5 = 24)

⚠️ 小结:

  • 每个 boolean[] 元素仍为 1 字节
  • 但数组有额外 4 字节长度字段
  • 加上对齐填充,小数组内存效率极低

例如:new boolean[1] 实际占用 24 字节(16 + 1 + 7 padding),有效数据仅 1 字节


6. 总结

场景 boolean 占用 说明
单个字段 1 字节 + 对齐填充 最小 1 字节,常因对齐浪费
数组元素 每个 1 字节 数组有额外 4 字节长度 + 对齐
总体结论 ❌ 不是 1 bit JVM 为避免 Word Tearing,强制 1 字节对齐

✅ 关键结论:

  • boolean 在 JVM 中占 1 字节,不是 1 bit
  • 对象头(12~16 字节)和对齐填充是主要“内存黑洞”
  • 小数组尤其浪费,不建议用 boolean[] 存大量标志位
  • 如需极致节省空间,考虑 BitSet 或位运算(如 long 用 64 bit 存 64 个 flag)

🔧 深入学习建议:

示例代码已托管至 GitHub:https://github.com/baeldung/core-java-modules/tree/master/core-java-jvm-2


原始标题:boolean and boolean[] Memory Layout in the JVM | Baeldung