zoukankan      html  css  js  c++  java
  • 【转】【堆外内存】堆内内存与堆外内存

    参考:https://www.cnblogs.com/ronnieyuan/p/11718536.html

    堆内内存:

    • 堆内内存是java程序员在日常工作中解除比较多的, 可以在jvm参数中使用-Xms, -Xmx 等参数来设置堆的大小和最大值

    • 堆内内存 = 年轻代 + 老年代 + 持久代(JDK1.8之前) 

    • 年轻代 (Young Generation)

      • 存放的是新生成的对象

      • 年轻代的目标是尽可能快速的收集掉那些生命周期短的对象

      • Eden

        • 大部分对象在Eden区中生成

        • 当Eden区满时, 依然存活的对象将被复制到Survivor区, 当一个Survivor 区满时, 此区的存活对象将被复制到另外一个Survivor区

      • Survivor(通常2个)

        • 当两个 Survivor 区 都满时, 从第一个Survivor 区 被复制过来 且 依旧存活的 对象会被复制到 老年区(Tenured)

        • Survivor 的两个区是对称的, 没有先后关系, 所有同一个区中可能同时存在从Eden复制过来的对象 和 从前一个 Survivor 复制过来的对象。

        • Survivor 区可以根据需要配置多个, 从而增加对象在年轻代的存在时间, 减少被放到老年代的可能。

    • 老年代 (Old Generation)

      • 存放了在年轻代中经历了N次垃圾回收后仍存活的对象, 是一些生命周期较长的对象
    • 持久代 (Permanent Generation)----方法区是Java虚拟机的规范,持久代(又叫永久代,实现了这个规范)

      • 存放静态文件, 如静态类和方法等。持久代对垃圾回收没有显著影响, 但是有些应用可能动态生成或者调用一些class, 比如Hibernate, Mybatis 等, 此时需要设置一个较大的持久代空间来存放这些运行过程中新增的类。

      • 设置持久代大小参数: -XX:MaxPermSize= Perm => Permanent

    • 垃圾回收(GC)

      • Scavenge GC
        • 一般当新对象生成并且在Eden申请空间失败时就会触发Scavenger GC, 对Eden区域进行GC, 清除非存活对象, 并且把尚存或的对象移动到Survivor区, 然后整理两个Survivor区。
        • 该方式的GC是对年轻代的Eden区进行,不会影响到年老代。
        • 由于大部分对象是从Eden区开始的, 同时Eden区分配的内存不会很大, 所以Eden区的GC会很频繁。
      • Full GC
        • 对整个堆进行整理, 包括Young, Tenured 和Permanent。
        • 所消耗的时间较长, 所以要尽量减少 Full GC 的次数
        • d导致 Full GC 的可能原因:
          • 老年代(Tenured) 被写满
          • 持久代(Permanent) 被写满
          • System.gc() 被显示调用
          • 上一次GC之后Heap 的各域分配策略动态变化
      • 常用垃圾回收算法
        • Reference Counting (引用计数算法)
        • Mark-Sweep (标记清除法)
        • Coping (复制法)
        • Mark-Compact (标记压缩法)
        • Generational Collecting (分代收集法)
        • Region (分区法)
        • GC Roots Tracing (可达性算法)      

    堆外内存(off-heap memory)

    • 定义

      • 堆外内存就是把内存对象分配在Java虚拟机的堆以外的内存
    • java.nio.DirectByteBuffer

      • Java 开发者经常用 java.nio.DirectByteBuffer 对象进行堆外内存的管理和使用, 该类会在创建对象时就分配堆外内存。

        • JDK1.8 取消了方法区, 由MetaSpace(元空间)代替。-XX:MaxPermSize由 -XX:MetaspaceSize, -XX:MaxMetaspaceSize 等代替

        • 对堆外内存的申请主要是通过成员变量unsafe来操作

      • package java.nio;
        
        import java.io.FileDescriptor;
        import sun.misc.Cleaner;
        import sun.misc.Unsafe;
        import sun.misc.VM;
        import sun.nio.ch.DirectBuffer;
        
        
        class DirectByteBuffer
        
            extends MappedByteBuffer
        
        
        
            implements DirectBuffer
        {
        
        
        
            // Cached unsafe-access object 缓存的unsafe获取对象
            protected static final Unsafe unsafe = Bits.unsafe();
        
            // Cached array base offset 缓存的数组基本偏移量
            private static final long arrayBaseOffset = (long)unsafe.arrayBaseOffset(byte[].class);
        
            // Cached unaligned-access capability 缓存的内存不对齐访问
            protected static final boolean unaligned = Bits.unaligned();
        
            // Base address, used in all indexing calculations 基本地址, 应用于所有参数运算
            // NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
            //    protected long address;
            // 基本地址呗移植到java 缓冲区 以 提升 JNI(Java Native Interface java 本地接口) 获取直接的缓存地址的 速度
        
            // An object attached to this buffer. If this buffer is a view of another
            // buffer then we use this field to keep a reference to that buffer to
            // ensure that its memory isn't freed before we are done with it.
            // 一个依附在 缓冲区的对象。 如果该Buffer是另一个buffer的视图, 我们需要使用该域来维持一个对于该缓冲区的记录来确保它的内存不在我们完成任务之前被释放
            private final Object att;
        
            public Object attachment() {
                return att;
            }
        
        
            // 重分配器(实现了Runnable接口, 是个线程)
            private static class Deallocator
                implements Runnable
            {
        
                private static Unsafe unsafe = Unsafe.getUnsafe();
                // 地址
                private long address;
                // 大小
                private long size;
                // 容量
                private int capacity;
        
                private Deallocator(long address, long size, int capacity) {
                    assert (address != 0);
                    this.address = address;
                    this.size = size;
                    this.capacity = capacity;
                }
        
                public void run() {
                    if (address == 0) {
                        // Paranoia 妄想... 如果没有地址就别想运行
                        return;
                    }
                     // 释放传入地址的内存
                    unsafe.freeMemory(address);
                    // 降地址设为0
                    address = 0;
                    // 去除保留内存
                    Bits.unreserveMemory(size, capacity);
                }
        
            }
            // 清理器
            private final Cleaner cleaner;
        
            public Cleaner cleaner() { return cleaner; }
        
        
        
        
        
        
        
        
        
        
        
            // Primary constructor 主要的构造器
            //
            DirectByteBuffer(int cap) {                   // package-private 私有包
        
                super(-1, 0, cap, cap);
                // 是否为页对齐的内存
                boolean pa = VM.isDirectMemoryPageAligned();
                // 获取页尺寸
                int ps = Bits.pageSize();
                long size = Math.max(1L, (long)cap + (pa ? ps : 0));
                // 保留内存
                Bits.reserveMemory(size, cap);
        
                long base = 0;
                try {
                    // 分配内存
                    base = unsafe.allocateMemory(size);
                } catch (OutOfMemoryError x) {
                    // 如果内存溢出就去除保留内存
                    Bits.unreserveMemory(size, cap);
                    throw x;
                }
                // 设置内存
                unsafe.setMemory(base, size, (byte) 0);
                if (pa && (base % ps != 0)) {
                    // Round up to page boundary 向上取整至页面边缘
                    address = base + ps - (base & (ps - 1));
                } else {
                    address = base;
                }
                cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
                att = null;
        
        
        
            }
        
        
        
            // Invoked to construct a direct ByteBuffer referring to the block of
            // memory. A given arbitrary object may also be attached to the buffer.
            // 请求构造一个直接的指向内存块的字节缓冲区。 一个已得的任意对象也可能依附于该缓冲区
            DirectByteBuffer(long addr, int cap, Object ob) {
                super(-1, 0, cap, cap);
                address = addr;
                cleaner = null;
                att = ob;
            }
        
        
            // Invoked only by JNI: NewDirectByteBuffer(void*, long)
            // 只被java本地接口请求
            private DirectByteBuffer(long addr, int cap) {
                super(-1, 0, cap, cap);
                address = addr;
                cleaner = null;
                att = null;
            }
        
        
        
            // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
            // 内存匹配的 缓冲区, 由NIO中 文件管道的 实现类 通过反射 请求
            protected DirectByteBuffer(int cap, long addr,
                                             FileDescriptor fd,
                                             Runnable unmapper)
            {
        
                super(-1, 0, cap, cap, fd);
                address = addr;
                cleaner = Cleaner.create(this, unmapper);
                att = null;
        
        
        
            }
        
        
        
            // For duplicates and slices 去重和切片
            //
            DirectByteBuffer(DirectBuffer db,         // package-private 私有包
                                       int mark, int pos, int lim, int cap,
                                       int off)
            {
        
                super(mark, pos, lim, cap);
                address = db.address() + off;
        
                cleaner = null;
        
                att = db;
        
        
        
            }
        
             // 切片
            public ByteBuffer slice() {
                // 当前位置
                int pos = this.position();
                // 限制界限
                int lim = this.limit();
                // 断言当前位置小于等于界限
                assert (pos <= lim);
                // 如果越界了就返回0
                int rem = (pos <= lim ? lim - pos : 0);
                // 不明白向左位移0位干嘛, 该位置还是该位置..., 获取偏移量
                int off = (pos << 0);
                // 断言偏移量 >= 0
                assert (off >= 0);
                return new DirectByteBuffer(this, -1, 0, rem, rem, off);
            }
        
            // 去重
            public ByteBuffer duplicate() {
                return new DirectByteBuffer(this,
                                                      this.markValue(),
                                                      this.position(),
                                                      this.limit(),
                                                      this.capacity(),
                                                      0);
            }
        
            // 设置为只读缓冲区       
            public ByteBuffer asReadOnlyBuffer() {
        
                return new DirectByteBufferR(this,
                                                   this.markValue(),
                                                   this.position(),
                                                   this.limit(),
                                                   this.capacity(),
                                                   0);
        
        
        
            }
        
        
        
            public long address() {
                return address;
            }
        
            private long ix(int i) {
                return address + ((long)i << 0);
            }
        
            public byte get() {
                return ((unsafe.getByte(ix(nextGetIndex()))));
            }
        
            public byte get(int i) {
                return ((unsafe.getByte(ix(checkIndex(i)))));
            }
        
        
        
        
        
        
            // 获取字节缓冲区
            public ByteBuffer get(byte[] dst, int offset, int length) {
        
                if (((long)length << 0) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
                    checkBounds(offset, length, dst.length);
                    int pos = position();
                    int lim = limit();
                    assert (pos <= lim);
                    int rem = (pos <= lim ? lim - pos : 0);
                    if (length > rem)
                        throw new BufferUnderflowException();
        
        
        
        
        
        
        
        
                        Bits.copyToArray(ix(pos), dst, arrayBaseOffset,
                                         (long)offset << 0,
                                         (long)length << 0);
                    position(pos + length);
                } else {
                    super.get(dst, offset, length);
                }
                return this;
        
        
        
            }
        
        
        
            public ByteBuffer put(byte x) {
        
                unsafe.putByte(ix(nextPutIndex()), ((x)));
                return this;
        
        
        
            }
        
            public ByteBuffer put(int i, byte x) {
        
                unsafe.putByte(ix(checkIndex(i)), ((x)));
                return this;
        
        
        
            }
        
            public ByteBuffer put(ByteBuffer src) {
        
                if (src instanceof DirectByteBuffer) {
                    if (src == this)
                        throw new IllegalArgumentException();
                    DirectByteBuffer sb = (DirectByteBuffer)src;
        
                    int spos = sb.position();
                    int slim = sb.limit();
                    assert (spos <= slim);
                    int srem = (spos <= slim ? slim - spos : 0);
        
                    int pos = position();
                    int lim = limit();
                    assert (pos <= lim);
                    int rem = (pos <= lim ? lim - pos : 0);
        
                    if (srem > rem)
                        throw new BufferOverflowException();
                    unsafe.copyMemory(sb.ix(spos), ix(pos), (long)srem << 0);
                    sb.position(spos + srem);
                    position(pos + srem);
                } else if (src.hb != null) {
        
                    int spos = src.position();
                    int slim = src.limit();
                    assert (spos <= slim);
                    int srem = (spos <= slim ? slim - spos : 0);
        
                    put(src.hb, src.offset + spos, srem);
                    src.position(spos + srem);
        
                } else {
                    super.put(src);
                }
                return this;
        
        
        
            }
        
            public ByteBuffer put(byte[] src, int offset, int length) {
        
                if (((long)length << 0) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
                    checkBounds(offset, length, src.length);
                    int pos = position();
                    int lim = limit();
                    assert (pos <= lim);
                    int rem = (pos <= lim ? lim - pos : 0);
                    if (length > rem)
                        throw new BufferOverflowException();
        
        
        
        
        
        
        
        
        
                        Bits.copyFromArray(src, arrayBaseOffset,
                                           (long)offset << 0,
                                           ix(pos),
                                           (long)length << 0);
                    position(pos + length);
                } else {
                    super.put(src, offset, length);
                }
                return this;
        
        
        
            }
            // 压缩
            public ByteBuffer compact() {
        
                int pos = position();
                int lim = limit();
                assert (pos <= lim);
                int rem = (pos <= lim ? lim - pos : 0);
        
                unsafe.copyMemory(ix(pos), ix(0), (long)rem << 0);
                position(rem);
                limit(capacity());
                discardMark();
                return this;
        
        
        
            }
            // 是否直接
            public boolean isDirect() {
                return true;
            }
            // 是否只读
            public boolean isReadOnly() {
                return false;
            }
        
        
        
        
        
            byte _get(int i) {                          // package-private
                return unsafe.getByte(address + i);
            }
        
            void _put(int i, byte b) {                  // package-private
        
                unsafe.putByte(address + i, b);
        
            }
        
        
        
        
            private char getChar(long a) {
                if (unaligned) {
                    char x = unsafe.getChar(a);
                    return (nativeByteOrder ? x : Bits.swap(x));
                }
                return Bits.getChar(a, bigEndian);
            }
        
            public char getChar() {
                return getChar(ix(nextGetIndex((1 << 1))));
            }
        
            public char getChar(int i) {
                return getChar(ix(checkIndex(i, (1 << 1))));
            }
        
        
        
            private ByteBuffer putChar(long a, char x) {
        
                if (unaligned) {
                    char y = (x);
                    unsafe.putChar(a, (nativeByteOrder ? y : Bits.swap(y)));
                } else {
                    Bits.putChar(a, x, bigEndian);
                }
                return this;
        
            }
        
            public ByteBuffer putChar(char x) {
        
                putChar(ix(nextPutIndex((1 << 1))), x);
                return this;
                
            }
        
            public ByteBuffer putChar(int i, char x) {
        
                putChar(ix(checkIndex(i, (1 << 1))), x);
                return this;
        
            }
            // 设置为char型的缓冲区
            public CharBuffer asCharBuffer() {
                int off = this.position();
                int lim = this.limit();
                assert (off <= lim);
                int rem = (off <= lim ? lim - off : 0);
        
                int size = rem >> 1;
                if (!unaligned && ((address + off) % (1 << 1) != 0)) {
                    return (bigEndian
                            ? (CharBuffer)(new ByteBufferAsCharBufferB(this,
                                                                               -1,
                                                                               0,
                                                                               size,
                                                                               size,
                                                                               off))
                            : (CharBuffer)(new ByteBufferAsCharBufferL(this,
                                                                               -1,
                                                                               0,
                                                                               size,
                                                                               size,
                                                                               off)));
                } else {
                    return (nativeByteOrder
                            ? (CharBuffer)(new DirectCharBufferU(this,
                                                                         -1,
                                                                         0,
                                                                         size,
                                                                         size,
                                                                         off))
                            : (CharBuffer)(new DirectCharBufferS(this,
                                                                         -1,
                                                                         0,
                                                                         size,
                                                                         size,
                                                                         off)));
                }
            }
        
        
        
        
            private short getShort(long a) {
                if (unaligned) {
                    short x = unsafe.getShort(a);
                    return (nativeByteOrder ? x : Bits.swap(x));
                }
                return Bits.getShort(a, bigEndian);
            }
        
            public short getShort() {
                return getShort(ix(nextGetIndex((1 << 1))));
            }
        
            public short getShort(int i) {
                return getShort(ix(checkIndex(i, (1 << 1))));
            }
        
        
        
            private ByteBuffer putShort(long a, short x) {
        
                if (unaligned) {
                    short y = (x);
                    unsafe.putShort(a, (nativeByteOrder ? y : Bits.swap(y)));
                } else {
                    Bits.putShort(a, x, bigEndian);
                }
                return this;
        
        
        
            }
        
            public ByteBuffer putShort(short x) {
        
                putShort(ix(nextPutIndex((1 << 1))), x);
                return this;
        
        
        
            }
        
            public ByteBuffer putShort(int i, short x) {
        
                putShort(ix(checkIndex(i, (1 << 1))), x);
                return this;
        
        
        
            }
            // 设置为short类型的缓冲区
            public ShortBuffer asShortBuffer() {
                int off = this.position();
                int lim = this.limit();
                assert (off <= lim);
                int rem = (off <= lim ? lim - off : 0);
        
                int size = rem >> 1;
                if (!unaligned && ((address + off) % (1 << 1) != 0)) {
                    return (bigEndian
                            ? (ShortBuffer)(new ByteBufferAsShortBufferB(this,
                                                                               -1,
                                                                               0,
                                                                               size,
                                                                               size,
                                                                               off))
                            : (ShortBuffer)(new ByteBufferAsShortBufferL(this,
                                                                               -1,
                                                                               0,
                                                                               size,
                                                                               size,
                                                                               off)));
                } else {
                    return (nativeByteOrder
                            ? (ShortBuffer)(new DirectShortBufferU(this,
                                                                         -1,
                                                                         0,
                                                                         size,
                                                                         size,
                                                                         off))
                            : (ShortBuffer)(new DirectShortBufferS(this,
                                                                         -1,
                                                                         0,
                                                                         size,
                                                                         size,
                                                                         off)));
                }
            }
        
        
        
        
            private int getInt(long a) {
                if (unaligned) {
                    int x = unsafe.getInt(a);
                    return (nativeByteOrder ? x : Bits.swap(x));
                }
                return Bits.getInt(a, bigEndian);
            }
        
            public int getInt() {
                return getInt(ix(nextGetIndex((1 << 2))));
            }
        
            public int getInt(int i) {
                return getInt(ix(checkIndex(i, (1 << 2))));
            }
        
        
        
            private ByteBuffer putInt(long a, int x) {
        
                if (unaligned) {
                    int y = (x);
                    unsafe.putInt(a, (nativeByteOrder ? y : Bits.swap(y)));
                } else {
                    Bits.putInt(a, x, bigEndian);
                }
                return this;
        
        
        
            }
        
            public ByteBuffer putInt(int x) {
        
                putInt(ix(nextPutIndex((1 << 2))), x);
                return this;
        
        
        
            }
        
            public ByteBuffer putInt(int i, int x) {
        
                putInt(ix(checkIndex(i, (1 << 2))), x);
                return this;
        
        
        
            }
            // 设置为Int类型的缓冲区
            public IntBuffer asIntBuffer() {
                int off = this.position();
                int lim = this.limit();
                assert (off <= lim);
                int rem = (off <= lim ? lim - off : 0);
        
                int size = rem >> 2;
                if (!unaligned && ((address + off) % (1 << 2) != 0)) {
                    return (bigEndian
                            ? (IntBuffer)(new ByteBufferAsIntBufferB(this,
                                                                               -1,
                                                                               0,
                                                                               size,
                                                                               size,
                                                                               off))
                            : (IntBuffer)(new ByteBufferAsIntBufferL(this,
                                                                               -1,
                                                                               0,
                                                                               size,
                                                                               size,
                                                                               off)));
                } else {
                    return (nativeByteOrder
                            ? (IntBuffer)(new DirectIntBufferU(this,
                                                                         -1,
                                                                         0,
                                                                         size,
                                                                         size,
                                                                         off))
                            : (IntBuffer)(new DirectIntBufferS(this,
                                                                         -1,
                                                                         0,
                                                                         size,
                                                                         size,
                                                                         off)));
                }
            }
        
        
        
        
            private long getLong(long a) {
                if (unaligned) {
                    long x = unsafe.getLong(a);
                    return (nativeByteOrder ? x : Bits.swap(x));
                }
                return Bits.getLong(a, bigEndian);
            }
        
            public long getLong() {
                return getLong(ix(nextGetIndex((1 << 3))));
            }
        
            public long getLong(int i) {
                return getLong(ix(checkIndex(i, (1 << 3))));
            }
        
        
        
            private ByteBuffer putLong(long a, long x) {
        
                if (unaligned) {
                    long y = (x);
                    unsafe.putLong(a, (nativeByteOrder ? y : Bits.swap(y)));
                } else {
                    Bits.putLong(a, x, bigEndian);
                }
                return this;
        
        
        
            }
        
            public ByteBuffer putLong(long x) {
        
                putLong(ix(nextPutIndex((1 << 3))), x);
                return this;
        
        
        
            }
        
            public ByteBuffer putLong(int i, long x) {
        
                putLong(ix(checkIndex(i, (1 << 3))), x);
                return this;
        
        
        
            }
            // 设置为long类型的缓冲区
            public LongBuffer asLongBuffer() {
                int off = this.position();
                int lim = this.limit();
                assert (off <= lim);
                int rem = (off <= lim ? lim - off : 0);
        
                int size = rem >> 3;
                if (!unaligned && ((address + off) % (1 << 3) != 0)) {
                    return (bigEndian
                            ? (LongBuffer)(new ByteBufferAsLongBufferB(this,
                                                                               -1,
                                                                               0,
                                                                               size,
                                                                               size,
                                                                               off))
                            : (LongBuffer)(new ByteBufferAsLongBufferL(this,
                                                                               -1,
                                                                               0,
                                                                               size,
                                                                               size,
                                                                               off)));
                } else {
                    return (nativeByteOrder
                            ? (LongBuffer)(new DirectLongBufferU(this,
                                                                         -1,
                                                                         0,
                                                                         size,
                                                                         size,
                                                                         off))
                            : (LongBuffer)(new DirectLongBufferS(this,
                                                                         -1,
                                                                         0,
                                                                         size,
                                                                         size,
                                                                         off)));
                }
            }
        
        
        
        
            private float getFloat(long a) {
                if (unaligned) {
                    int x = unsafe.getInt(a);
                    return Float.intBitsToFloat(nativeByteOrder ? x : Bits.swap(x));
                }
                return Bits.getFloat(a, bigEndian);
            }
        
            public float getFloat() {
                return getFloat(ix(nextGetIndex((1 << 2))));
            }
        
            public float getFloat(int i) {
                return getFloat(ix(checkIndex(i, (1 << 2))));
            }
        
        
        
            private ByteBuffer putFloat(long a, float x) {
        
                if (unaligned) {
                    int y = Float.floatToRawIntBits(x);
                    unsafe.putInt(a, (nativeByteOrder ? y : Bits.swap(y)));
                } else {
                    Bits.putFloat(a, x, bigEndian);
                }
                return this;
        
        
        
            }
        
            public ByteBuffer putFloat(float x) {
        
                putFloat(ix(nextPutIndex((1 << 2))), x);
                return this;
        
        
        
            }
        
            public ByteBuffer putFloat(int i, float x) {
        
                putFloat(ix(checkIndex(i, (1 << 2))), x);
                return this;
        
        
        
            }
            // 设置为Float类型的缓冲区
            public FloatBuffer asFloatBuffer() {
                int off = this.position();
                int lim = this.limit();
                assert (off <= lim);
                int rem = (off <= lim ? lim - off : 0);
        
                int size = rem >> 2;
                if (!unaligned && ((address + off) % (1 << 2) != 0)) {
                    return (bigEndian
                            ? (FloatBuffer)(new ByteBufferAsFloatBufferB(this,
                                                                               -1,
                                                                               0,
                                                                               size,
                                                                               size,
                                                                               off))
                            : (FloatBuffer)(new ByteBufferAsFloatBufferL(this,
                                                                               -1,
                                                                               0,
                                                                               size,
                                                                               size,
                                                                               off)));
                } else {
                    return (nativeByteOrder
                            ? (FloatBuffer)(new DirectFloatBufferU(this,
                                                                         -1,
                                                                         0,
                                                                         size,
                                                                         size,
                                                                         off))
                            : (FloatBuffer)(new DirectFloatBufferS(this,
                                                                         -1,
                                                                         0,
                                                                         size,
                                                                         size,
                                                                         off)));
                }
            }
        
        
        
        
            private double getDouble(long a) {
                if (unaligned) {
                    long x = unsafe.getLong(a);
                    return Double.longBitsToDouble(nativeByteOrder ? x : Bits.swap(x));
                }
                return Bits.getDouble(a, bigEndian);
            }
        
            public double getDouble() {
                return getDouble(ix(nextGetIndex((1 << 3))));
            }
        
            public double getDouble(int i) {
                return getDouble(ix(checkIndex(i, (1 << 3))));
            }
        
        
        
            private ByteBuffer putDouble(long a, double x) {
        
                if (unaligned) {
                    long y = Double.doubleToRawLongBits(x);
                    unsafe.putLong(a, (nativeByteOrder ? y : Bits.swap(y)));
                } else {
                    Bits.putDouble(a, x, bigEndian);
                }
                return this;
        
        
        
            }
        
            public ByteBuffer putDouble(double x) {
        
                putDouble(ix(nextPutIndex((1 << 3))), x);
                return this;
        
        
        
            }
        
            public ByteBuffer putDouble(int i, double x) {
        
                putDouble(ix(checkIndex(i, (1 << 3))), x);
                return this;
        
        
        
            }
            // 设置为double类型的缓冲区
            public DoubleBuffer asDoubleBuffer() {
                int off = this.position();
                int lim = this.limit();
                assert (off <= lim);
                int rem = (off <= lim ? lim - off : 0);
        
                int size = rem >> 3;
                if (!unaligned && ((address + off) % (1 << 3) != 0)) {
                    return (bigEndian
                            ? (DoubleBuffer)(new ByteBufferAsDoubleBufferB(this,
                                                                               -1,
                                                                               0,
                                                                               size,
                                                                               size,
                                                                               off))
                            : (DoubleBuffer)(new ByteBufferAsDoubleBufferL(this,
                                                                               -1,
                                                                               0,
                                                                               size,
                                                                               size,
                                                                               off)));
                } else {
                    return (nativeByteOrder
                            ? (DoubleBuffer)(new DirectDoubleBufferU(this,
                                                                         -1,
                                                                         0,
                                                                         size,
                                                                         size,
                                                                         off))
                            : (DoubleBuffer)(new DirectDoubleBufferS(this,
                                                                         -1,
                                                                         0,
                                                                         size,
                                                                         size,
                                                                         off)));
                }
            }
        
        }

         
  • 相关阅读:
    浅析Java8新特性-Optional方法介绍(Optional.ofNullable-构造方法、map-逐层安全地拆解value、filter-过滤值、orElse/orElseThrow-最终返回、stream-转为流)及常用实践(仅作为方法返回值、清晰地表达返回值中没有结果的可能性、勿滥用Optional)、Optional的设计思想实现
    浅析Java8新特性-新的日期和时间API:起初时间存在的问题(非线程安全、设计乱、时区处理麻烦)、日期时间(LocalDate/LocalTime/LocalDateTime)、时间戳(Instant)、时间差(Duration/Period)、TemporalAdjuster时间矫正器、LocalDateTime 与 Date 互转、时间先后判断/MonthDay类的使用(生日检查)
    浅析 Employee::new / String[]::new 是什么意思?Java8新特性-方法引用、构造器引用、数组引用的了解及使用
    浅析HTTP的Referer含义理解、Referer作用(记录访问来源、防盗链、防止恶意请求)、Referrer Policy引用策略的9个值及设置用法、什么情况会导致空Referer
    浅析Java8新特性-四大内置核心函数式接口 :消费型Consumer(void accept)、供给型Supplier(T get)、函数型Funciton(R apply)、断言型Predicate(boolean test)
    浅析Java Lambda表达式、如何理解Lambda、如何使用Lambda简化代码(结合stream处理遍历、配合Optional优雅的处理null情况)
    【原文】linux systemctl命令详解
    [转]解决Ubuntu DNS覆盖写入127.0.0.53
    mysql 安装
    【转】lvextend 无法使用 virtualbox 扩容的vdi
  • 原文地址:https://www.cnblogs.com/july-sunny/p/14478820.html
Copyright © 2011-2022 走看看