/** * Relative <i>get</i> method for reading an int value. * * <p> Reads the next four bytes at this buffer's current position, * composing them into an int value according to the current byte order, * and then increments the position by four. </p> * * @return The int value at the buffer's current position * * @throws BufferUnderflowException * If there are fewer than four bytes * remaining in this buffer */ publicabstractintgetInt();
/** * Absolute <i>get</i> method for reading an int value. * * <p> Reads four bytes at the given index, composing them into a * int value according to the current byte order. </p> * * @param index * The index from which the bytes will be read * * @return The int value at the given index * * @throws IndexOutOfBoundsException * If <tt>index</tt> is negative * or not smaller than the buffer's limit, * minus three */ publicabstractintgetInt(int index);
// These numbers represent the point at which we have empirically determined that the average cost of a JNI call exceeds the expense of an element by element copy.These numbers may change over time. staticfinalint JNI_COPY_TO_ARRAY_THRESHOLD = 6;
A limit is imposed to allow for safepoint polling during a large copy staticfinallong UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
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) thrownew BufferUnderflowException(); Bits.copyToArray(ix(pos), dst, arrayBaseOffset, (long)offset << 0, (long)length << 0); position(pos + length); } else { super.get(dst, offset, length); } returnthis; }
staticvoidcopyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos, long length){ long offset = dstBaseOffset + dstPos; while (length > 0) { long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length; unsafe.copyMemory(null, srcAddr, dst, offset, size); length -= size; srcAddr += size; offset += size; } }
public ByteBuffer get(byte[] dst, int offset, int length){ checkBounds(offset, length, dst.length); if (length > remaining()) thrownew BufferUnderflowException();
int end = offset + length; for (int i = offset; i < end; i++) { dst[i] = get(); } returnthis; }
unsafe 操作
Spark 有一套Platform可以很方便的操作(占个坑先, 日后研究发).
1 2 3 4 5 6 7 8 9 10 11 12 13
Field address = Buffer.class.getDeclaredField("address"); address.setAccessible(true); long baseAddress = (long) address.get(buffer);
public void copyMemory(int pos, byte[] dst, int offset, int length) { Platform.copyMemory(null, ix(pos), dst, BYTE_ARRAY_OFFSET + ((long) offset << 0), (long) length << 0); }
private long ix(int i) { return baseAddress + ((long) i << 0); }