zoukankan      html  css  js  c++  java
  • java中的大端和小端存储

    前言

    • 字节序:
      指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序,有大端和小端两种方式
    • 大端:
      指高位字节存放在内存的低地址端,低位字节存放在内存的高地址端。
    • 小端:
      指低位字节放在内存的低地址端,高位字节放在内存的高地址端。

    以一个int值 0x01020304 为例

    存储方式和CPU架构有关,IA架构(Intel、AMD)的CPU中是Little-Endian,而PowerPC 、SPARC和Motorola是Big-Endian

    获取CPU使用的存储方式

    在windows下

    import java.nio.ByteOrder;
    
    public class Client {
    
      public static void main(String[] args) {
        System.out.println(ByteOrder.nativeOrder());
      }
    }
    

    输出为

    LITTLE_ENDIAN
    

    java8中的实现原理为

    public static ByteOrder nativeOrder() {
            return Bits.byteOrder();
        }
    
    static ByteOrder byteOrder() {
            if (byteOrder == null)
                throw new Error("Unknown byte order");
            return byteOrder;
        }
    
        static {
            long a = unsafe.allocateMemory(8);
            try {
                unsafe.putLong(a, 0x0102030405060708L);
                byte b = unsafe.getByte(a);
                switch (b) {
                case 0x01: byteOrder = ByteOrder.BIG_ENDIAN;     break;
                case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN;  break;
                default:
                    assert false;
                    byteOrder = null;
                }
            } finally {
                unsafe.freeMemory(a);
            }
        }
    

    java11中实现原理为

    public static ByteOrder nativeOrder() {
            return NATIVE_ORDER;
        }
    
    private static final ByteOrder NATIVE_ORDER
            = Unsafe.getUnsafe().isBigEndian()
                ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
    
    public final boolean isBigEndian() { return BE; }
    
    private static final boolean BE = theUnsafe.isBigEndian0();
    
    private native boolean isBigEndian0();
    

    修改java中的存储方式

    java中默认使用大端

    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.util.Arrays;
    
    public class Client {
    
      public static void main(String[] args) {
        int x = 0x01020304;
        ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[4]);
        byteBuffer.asIntBuffer().put(x);
        String before = Arrays.toString(byteBuffer.array());
        System.out.println("默认字节序:" + byteBuffer.order().toString() + "," + "内存数据:" + before);
    
        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
        byteBuffer.asIntBuffer().put(x);
        String after = Arrays.toString(byteBuffer.array());
        System.out.println("小端字节序:" + byteBuffer.order().toString() + "," + "内存数据:" + after);
      }
    }
    

    输出为

    默认字节序:BIG_ENDIAN,内存数据:[1, 2, 3, 4]
    小端字节序:LITTLE_ENDIAN,内存数据:[4, 3, 2, 1]
    

    源码实现为

    public IntBuffer asIntBuffer() {
            int size = this.remaining() >> 2;
            long addr = address + position();
            return (bigEndian
                    ? (IntBuffer)(new ByteBufferAsIntBufferB(this,
                                                                 -1,
                                                                 0,
                                                                 size,
                                                                 size,
                                                                 addr))
                    : (IntBuffer)(new ByteBufferAsIntBufferL(this,
                                                                 -1,
                                                                 0,
                                                                 size,
                                                                 size,
                                                                 addr)));
        }
    
    public IntBuffer put(int x) {
    
            int y = (x);
            UNSAFE.putIntUnaligned(bb.hb, byteOffset(nextPutIndex()), y,
                true);
            return this;
        }
    
    /** @see #putLongUnaligned(Object, long, long, boolean) */
        public final void putIntUnaligned(Object o, long offset, int x, boolean bigEndian) {
            putIntUnaligned(o, offset, convEndian(bigEndian, x));
        }
    

    核心在于

    private static int convEndian(boolean big, int n)     { return big == BE ? n : Integer.reverseBytes(n)  ; }
    

    参考

    Java中的大端和小端
    java字节序、主机字节序和网络字节序扫盲贴
    java内存,大端小端判断

  • 相关阅读:
    BZOJ 4769: 超级贞鱼 逆序对 + 归并排序
    BZOJ 4897: [Thu Summer Camp2016]成绩单 动态规划
    luogu 4059 [Code+#1]找爸爸 动态规划
    CF718C Sasha and Array 线段树 + 矩阵乘法
    计蒜客 2238 礼物 期望 + 线段树 + 归并
    BZOJ 2157: 旅游 (结构体存变量)
    BZOJ 3786: 星系探索 ETT
    BZOJ 3545: [ONTAK2010]Peaks 启发式合并 + 离线 + Splay
    Spring的几种初始化和销毁方法
    SpringCloud之Zuul高并发情况下接口限流(十二)
  • 原文地址:https://www.cnblogs.com/strongmore/p/14920007.html
Copyright © 2011-2022 走看看