字节序:指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序,有大端和小端两种方式,在不同的应用场景下这两种存储各有优势。
大端:指高位字节存放在内存的低地址端,低位字节存放在内存的高地址端。十六进制整数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类直接操作内存进行验证。

  1. private static Unsafe getUnsafe() {
  2. try {
  3. Field field = Unsafe.class.getDeclaredField("theUnsafe");
  4. field.setAccessible(true);
  5. return (Unsafe) field.get(null);
  6. } catch (Exception e) {
  7. return null;
  8. }
  9. }
  10. public static void main(String[] args) {
  11. final Unsafe unsafe = getUnsafe();
  12. final long addr = unsafe.allocateMemory(2);
  13. unsafe.putShort(addr, (short) 1);
  14. final byte lowerNum = unsafe.getByte(addr);//获取一个字节
  15. System.out.println(lowerNum);
  16. // 存放一个超过一个字节大小的数 如256->第二个字节第一位为1
  17. unsafe.putShort(addr, (short) 256);
  18. final byte higherNum = unsafe.getByte(addr + 1);// 获取第二个字节数据
  19. System.out.println(higherNum);
  20. }

输出:

1 1

jvm对对象头的存储

先上示例
添加依赖

  1. <dependency>
  2. <groupId>org.openjdk.jol</groupId>
  3. <artifactId>jol-core</artifactId>
  4. <version>0.9</version>
  5. </dependency>

实例对象

  1. public class Worker {
  2. private Integer id;
  3. private String username;
  4. private String password;
  5. private short age;
  6. }

测试代码

  1. public static void main(String[] args) {
  2. Worker work = new Worker();
  3. // hashCode
  4. System.out.println("hashCode: " + work.hashCode() + " 十六进制表示:0X" + HexUtil.toHex(work.hashCode()));
  5. // 对象内存布局
  6. System.out.println(ClassLayout.parseInstance(work).toPrintable());
  7. }

输出:

  1. hashCode: 1735600054 十六进制表示:0X677327b6
  2. com.obj.header.Worker object internals:
  3. OFFSET SIZE TYPE DESCRIPTION VALUE
  4. 0 4 (object header) 01 b6 27 73 (00000001 10110110 00100111 01110011) (1931982337)
  5. 4 4 (object header) 67 00 00 00 (01100111 00000000 00000000 00000000) (103)
  6. 8 4 (object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)
  7. 12 2 short Worker.age 0
  8. 14 2 (alignment/padding gap)
  9. 16 4 java.lang.Integer Worker.id null
  10. 20 4 java.lang.String Worker.username null
  11. 24 4 java.lang.String Worker.password null
  12. 28 4 (loss due to the next object alignment)
  13. Instance size: 32 bytes
  14. Space losses: 2 bytes internal + 4 bytes external = 6 bytes total

对比可见实例对象的hashcode是大端存储。