字节序:指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序,有大端和小端两种方式,在不同的应用场景下这两种存储各有优势。
大端:指高位字节存放在内存的低地址端,低位字节存放在内存的高地址端。十六进制整数0x01020304在内存中存储方式,由于一个整型在内存中占4个字节,因此被划分成4份分别存储在连续的内存地址位中
内存地址 | 0x004060 | 0x004061 | 0x004062 | 0x004063 |
---|---|---|---|---|
数据值 | 01 | 02 | 03 | 04 |
小端:指低位字节放在内存的低地址端,高位字节放在内存的高地址端。同样0x01020304在内存中的存储方式为
内存地址 | 0x004060 | 0x004061 | 0x004062 | 0x004063 |
---|---|---|---|---|
数据值 | 04 | 03 | 02 | 01 |
jvm对基本数字类型的存储
在java基本类型中,诸如赋值语句byte a = (byte)1;
从使用上不难看出这是小端存储的方式,才能安全的向下转型。
同时我们可以用UnSafe
类直接操作内存进行验证。
private static Unsafe getUnsafe() {
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);
} catch (Exception e) {
return null;
}
}
public static void main(String[] args) {
final Unsafe unsafe = getUnsafe();
final long addr = unsafe.allocateMemory(2);
unsafe.putShort(addr, (short) 1);
final byte lowerNum = unsafe.getByte(addr);//获取一个字节
System.out.println(lowerNum);
// 存放一个超过一个字节大小的数 如256->第二个字节第一位为1
unsafe.putShort(addr, (short) 256);
final byte higherNum = unsafe.getByte(addr + 1);// 获取第二个字节数据
System.out.println(higherNum);
}
输出:
1 1
jvm对对象头的存储
先上示例
添加依赖
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
实例对象
public class Worker {
private Integer id;
private String username;
private String password;
private short age;
}
测试代码
public static void main(String[] args) {
Worker work = new Worker();
// hashCode
System.out.println("hashCode: " + work.hashCode() + " 十六进制表示:0X" + HexUtil.toHex(work.hashCode()));
// 对象内存布局
System.out.println(ClassLayout.parseInstance(work).toPrintable());
}
输出:
hashCode: 1735600054 十六进制表示:0X677327b6
com.obj.header.Worker object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 b6 27 73 (00000001 10110110 00100111 01110011) (1931982337)
4 4 (object header) 67 00 00 00 (01100111 00000000 00000000 00000000) (103)
8 4 (object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)
12 2 short Worker.age 0
14 2 (alignment/padding gap)
16 4 java.lang.Integer Worker.id null
20 4 java.lang.String Worker.username null
24 4 java.lang.String Worker.password null
28 4 (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 2 bytes internal + 4 bytes external = 6 bytes total
对比可见实例对象的hashcode是大端存储。