java - Java 中字符串表示的不同大小

标签 java

我通过将 String 分解成其组成部分来比较在 java 中存储 String 的各种方法。我有这个代码片段:

final String message = "ABCDEFGHIJ";
System.out.println("As String " + RamUsageEstimator.humanSizeOf(message));
System.out.println("As byte[] " + RamUsageEstimator.humanSizeOf(message.getBytes()));
System.out.println("As char[] " + RamUsageEstimator.humanSizeOf(message.toCharArray()));

这是使用 sizeof来测量物体的大小。以上结果显示:

As String 64 bytes
As byte[] 32 bytes
As char[] 40 bytes

鉴于 byte 是 8 位而 char 是 16 位,为什么结果分别不是 10 字节和 20 字节?

此外,String 对象的开销是基础 byte[] 的两倍?

这是在使用

java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

在 OSX 上

最佳答案

以下数据适用于 Hotspot/Java 8 - 其他 JVM/Java 版本的数字会有所不同(例如,在 Java 7 中,String 有两个额外的 int 字段).

new Object() 占用 12 个字节的内存(由于对象头等内部事物)。

一个字符串有(括号中的字节数):

  • 一个对象头(12),
  • char[] 的引用(4 - 假设在 64 位 JVM 中压缩 OOP),
  • int hash (4)。

那是 20 个字节,但是对象被填充到 8 字节的倍数 => 24。所以这已经是数组实际内容之上的 24 个字节。

char[] 有一个标题 (12)、一个长度 (4) 和每个字符 (10 x 2 = 20) 填充到下一个 8 的倍数 - 或总共 40。

byte[] 有一个 header (12)、一个长度 (4) 和每个字节 (10 x 1 = 10) = 26,填充到下一个 8 的倍数 = 32。

所以我们得到了你的数字。

另请注意,字节数取决于您使用的编码 - 例如,如果您使用 message.getBytes(StandardCharsets.UTF_16) 重试,您将看到字节数组使用 40 个字节共 32 个。


您可以使用 jol可视化内存使用情况并确认上面的计算。 char[] 的输出是:

 OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
      0     4       (object header)                01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4       (object header)                00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4       (object header)                41 00 00 f8 (01000001 00000000 00000000 11111000) (-134217663)
     12     4       (object header)                0a 00 00 00 (00001010 00000000 00000000 00000000) (10)
     16    20  char [C.<elements>                  N/A
     36     4       (loss due to the next object alignment)
Instance size: 40 bytes (reported by Instrumentation API)

因此您可以看到 12 的标题(前 3 行)、长度(第 4 行)、字符(第 5 行)和填充(第 6 行)。

与字符串类似(注意这不包括数组本身的大小):

 OFFSET  SIZE   TYPE DESCRIPTION                    VALUE
      0     4        (object header)                01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                da 02 00 f8 (11011010 00000010 00000000 11111000) (-134216998)
     12     4 char[] String.value                   [A, B, C, D, E, F, G, H, I, J]
     16     4    int String.hash                    0
     20     4        (loss due to the next object alignment)
Instance size: 24 bytes (reported by Instrumentation API)

关于java - Java 中字符串表示的不同大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35337565/

相关文章:

Java主机系统架构

java - 我如何在 Gradle 中运行 JUnit 测试

java - '' 作为 <alias> 有什么作用?

java - 如何将 <junit> 任务的工作目录设置为 basedir 以外的目录?

java - 为什么 Cryptoki.C_OpenSession 有时会与 HSM 断开连接

java - 如何在 jboss 中禁用主机名验证

java - set add方法问题的无序尾部链表实现

java - 对于 HttpGet 类型,方法 addHeader (String, String) 未定义

java - 在 MockitoJUnitRunner 下运行测试时,DAO 未 Autowiring

java - 如何通过 JSON API 实现复杂的条件批量部分更新?