最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

boolean 与boolean数组内存布局

网站源码admin1浏览0评论

boolean 与boolean数组内存布局

1. 概述

在这篇快速文章中,我们将看到在不同情况下 JVM 中布尔值的足迹是多少。

首先,我们将检查 JVM 以查看对象大小。然后,我们将了解这些尺寸背后的基本原理。

2. 设置

为了检查 JVM 中对象的内存布局,我们将广泛使用 Java 对象布局 (JOL)。因此,我们需要添加jol-core依赖项:

代码语言:javascript代码运行次数:0运行复制
<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.10</version>
</dependency>Copy

3. 对象尺寸

如果我们要求 JOL 根据对象大小打印虚拟机详细信息:

代码语言:javascript代码运行次数:0运行复制
System.out.println(VM.current().details());Copy

启用压缩引用(默认行为)后,我们将看到输出:

代码语言:javascript代码运行次数:0运行复制
# 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]Copy

在前几行中,我们可以看到有关 VM 的一些常规信息。之后,我们了解对象大小:

  • Java 引用4个字节,布尔/字节是1个字节,char/short是2个字节,int/float是4个字节,最后,long /double是8个字节
  • 即使我们将这些类型用作数组元素,它们也会消耗相同的内存量

因此,在存在压缩引用的情况下,每个布尔值占用 1 个字节。同样,布尔数组 中的每个布尔值消耗 1 个字节。但是,对齐填充和对象标题会增加布尔和布尔数组占用的空间,我们将在后面看到。

3.1. 无压缩引用

即使我们通过 XX:-UseCompressedOops 禁用压缩引用,布尔大小也不会改变:

代码语言:javascript代码运行次数:0运行复制
# Field sizes by type: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]Copy

另一方面,Java 引用占用了两倍的内存。

因此,尽管我们一开始可能期望,布尔值消耗 1 个字节,而不仅仅是 1 位。

3.2. 单词撕裂

在大多数体系结构中,没有办法以原子方式访问单个位。即使我们想这样做,我们可能会在更新另一个位的同时写入相邻的位。

JVM的设计目标之一就是防止这种现象,即所谓的单词撕裂。也就是说,在JVM中,每个字段和数组元素都应该是不同的;对一个字段或元素的更新不能与任何其他字段或元素的读取或更新交互。

概括一下,可寻址性问题和单词撕裂是布尔值不止一个比特的主要原因。

4. 普通对象指针 (OOP)

现在我们知道布尔值是 1 个字节,让我们考虑这个简单的类:

代码语言:javascript代码运行次数:0运行复制
class BooleanWrapper {
    private boolean value;
}Copy

如果我们使用 JOL 检查此类的内存布局:

代码语言:javascript代码运行次数:0运行复制
System.out.println(ClassLayout.parseClass(BooleanWrapper.class).toPrintable());Copy

然后 JOL 将打印内存布局:

代码语言:javascript代码运行次数:0运行复制
 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 totalCopy

BooleanWrapper布局包括:

  • 标头为 12 个字节,包括两个标记字和一个klass字。HotSpot JVM使用标记字来存储GC元数据,身份哈希码和锁定信息。此外,它还使用klass字来存储类元数据,例如运行时类型检查
  • 1 字节的实际布尔
  • 3字节的填充用于对齐目的

默认情况下,对象引用应按 8 个字节对齐。因此,JVM 将 3 个字节添加到 13 个字节的标头和布尔值中,使其成为 16 个字节。

因此,布尔字段可能会因其字段对齐而消耗更多内存。

4.1. 自定义对齐方式

如果我们将对齐值更改为 32 via-XX:ObjectAlignmentInBytes=32,则相同的类布局将更改为:

代码语言:javascript代码运行次数:0运行复制
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
Space losses: 0 bytes internal + 19 bytes external = 19 bytes totalCopy

如上所示,JVM 添加了 19 个字节的填充,使对象大小成为 32 的倍数。

5. Array OOPs

让我们看看 JVM 如何在内存中布置一个布尔数组:

代码语言:javascript代码运行次数:0运行复制
boolean[] value = new boolean[3];
System.out.println(ClassLayout.parseInstance(value).toPrintable());Copy

这将打印实例布局,如下所示:

代码语言:javascript代码运行次数:0运行复制
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)Copy

除了两个标记字和一个klass字外,数组指针还包含额外的 4 个字节来存储它们的长度。

由于我们的数组有三个元素,因此数组元素的大小为 3 个字节。但是,这 3 个字节将填充 5 个字段对齐字节以确保正确对齐。

尽管数组中的每个布尔元素只有 1 个字节,但整个数组消耗的内存要多得多。换句话说,在计算数组大小时,我们应该考虑标头和填充开销。

6. 结论

在这个快速教程中,我们看到布尔字段消耗 1 个字节。此外,我们了解到我们应该考虑对象大小的标题和填充开销。

对于更详细的讨论,强烈建议查看JVM 源代码的 oops 部分。此外,阿列克谢·希皮利夫在这方面有一篇更深入的文章。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2023-02-24,如有侵权请联系 cloudcommunity@tencent 删除内存数组boolean布局教程

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论