跳至主要內容

JVM Inst

Someone大约 3 分钟JAVAjvmjava

Abstract

JAVA 字符串操作的优化。

Java 对象布局

Java Array 对象布局

Java Char Array
HeadMark Word4 Bytes
Class Pointer4 Bytes
Length of ArrayOffset = 8
Instance DataData of Array
Padding

Data of Array 中的每个 char 占 2 Bytes.

加载Length的流程包括:

  1. 需要通过数组实例的基地址加载Length的值。
  2. 如果基地址错误,需要返回错误码。
  3. 如果length为0,需要返回错误码。

字符串数组的简化布局:

+------------------+
| 对象头 | // 包含元数据
+------------------+
| length (int) | // 数组长度 (2)
+------------------+
| 引用1 | // 指向 "Hello" 字符串对象
+------------------+
| 引用2 | // 指向 "World" 字符串对象
+------------------+

64 位 JVM 中,对象头为 16 字节,长度占 4 字节(存储字符串长度的 int),每一个引用占用 8 字节(32 位系统中占用 4 字节)

Java String 对象布局

Java String
HeadMark Word4 Bytes
Class Pointer4 Bytes
Instance DataData of ArrayOffset=8
Raw Data
Padding

加载Length的流程包括:

  1. 需要通过 String 实例的基地址加载 Length 的值。
  2. 如果基地址错误,需要返回错误码。
  3. 如果length为0,需要返回错误码。
  4. String 的 Length 的最低位是 TAG-bit,表示是否压缩,需要移位去除掉

字符串的简化内存布局如下所示:

+------------------+
| 对象头 | // 包含元数据
+------------------+
| length (int) | // 字符串长度
+------------------+
| char[] | // 存储字符 'H', 'e', 'l', 'l', 'o'
+------------------+

对象头,16 字节,长度 4 字节,每个字符占用 2 字节(因为 UTF-16 编码)

常见对象的大小

对于基本的数据类型:
boolean: 1 字节(通常在对象中占用 4 字节或 8 字节,因为对象的对齐)
byte: 1 字节
char: 2 字节(UTF-16 编码)
short: 2 字节
int: 4 字节
float: 4 字节
long: 8 字节
double: 8 字节

对于对象头:对象头通常占用 12 字节(在 64 位 JVM 中,可能为 16 字节,具体取决于对象对齐和是否启用了指针压缩)

对于对象:大约 12 字节(在 64 位 JVM 中,可能为 16 字节)
+---------------------+
| 对象头 | // 12 字节(或 16 字节)
+---------------------+
| name (String) | // 4 字节(在 32 位 JVM 中)或 8 字节(在 64 位 JVM 中)
+---------------------+
| age (int) | // 4 字节
+---------------------+
| 填充 (Padding) | // 可能存在,确保对齐
+---------------------+

JInst

  1. 加载字符数组的长度,并检查对象的指针的合法性;
  2. 加载字符串对象的长度,并检查对象的指针的合法性;
  3. 检查给定的开始和结束点是否在合法范围内;
  4. 检查给定的开始和长度是否在合法范围内;
  5. 针对 Java 的字符串拷贝。

1 和 2 都是基于 Java 内存布局进行的加载,并在异常时返回。3 和 4 帮助检查给定的开始和结束是否在合法的长度范围内。

MemCpy Opt

Java 的对象是关于 32Bit 对齐的,而 Java 的字符存储分为 Bytes 的压缩格式和 2XBytes 的宽字符格式,