Fetch the repository succeeded.
This action will force synchronization from cxylk/Java-Notes, which will overwrite any changes that you have made since you forked the repository, and can not be recovered!!!
Synchronous operation will process in the background and will refresh the page when finishing processing. Please be patient.
/*
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package java.nio;
import java.security.AccessController;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import sun.misc.JavaLangRefAccess;
import sun.misc.SharedSecrets;
import sun.misc.Unsafe;
import sun.misc.VM;
/**
* Access to bits, native and otherwise.
*/
class Bits { // package-private
private Bits() { }
// -- Swapping --
static short swap(short x) {
return Short.reverseBytes(x);
}
static char swap(char x) {
return Character.reverseBytes(x);
}
static int swap(int x) {
return Integer.reverseBytes(x);
}
static long swap(long x) {
return Long.reverseBytes(x);
}
// -- get/put char --
static private char makeChar(byte b1, byte b0) {
return (char)((b1 << 8) | (b0 & 0xff));
}
static char getCharL(ByteBuffer bb, int bi) {
return makeChar(bb._get(bi + 1),
bb._get(bi ));
}
static char getCharL(long a) {
return makeChar(_get(a + 1),
_get(a ));
}
static char getCharB(ByteBuffer bb, int bi) {
return makeChar(bb._get(bi ),
bb._get(bi + 1));
}
static char getCharB(long a) {
return makeChar(_get(a ),
_get(a + 1));
}
static char getChar(ByteBuffer bb, int bi, boolean bigEndian) {
return bigEndian ? getCharB(bb, bi) : getCharL(bb, bi);
}
static char getChar(long a, boolean bigEndian) {
return bigEndian ? getCharB(a) : getCharL(a);
}
private static byte char1(char x) { return (byte)(x >> 8); }
private static byte char0(char x) { return (byte)(x ); }
static void putCharL(ByteBuffer bb, int bi, char x) {
bb._put(bi , char0(x));
bb._put(bi + 1, char1(x));
}
static void putCharL(long a, char x) {
_put(a , char0(x));
_put(a + 1, char1(x));
}
static void putCharB(ByteBuffer bb, int bi, char x) {
bb._put(bi , char1(x));
bb._put(bi + 1, char0(x));
}
static void putCharB(long a, char x) {
_put(a , char1(x));
_put(a + 1, char0(x));
}
static void putChar(ByteBuffer bb, int bi, char x, boolean bigEndian) {
if (bigEndian)
putCharB(bb, bi, x);
else
putCharL(bb, bi, x);
}
static void putChar(long a, char x, boolean bigEndian) {
if (bigEndian)
putCharB(a, x);
else
putCharL(a, x);
}
// -- get/put short --
static private short makeShort(byte b1, byte b0) {
return (short)((b1 << 8) | (b0 & 0xff));
}
static short getShortL(ByteBuffer bb, int bi) {
return makeShort(bb._get(bi + 1),
bb._get(bi ));
}
static short getShortL(long a) {
return makeShort(_get(a + 1),
_get(a ));
}
static short getShortB(ByteBuffer bb, int bi) {
return makeShort(bb._get(bi ),
bb._get(bi + 1));
}
static short getShortB(long a) {
return makeShort(_get(a ),
_get(a + 1));
}
static short getShort(ByteBuffer bb, int bi, boolean bigEndian) {
return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi);
}
static short getShort(long a, boolean bigEndian) {
return bigEndian ? getShortB(a) : getShortL(a);
}
private static byte short1(short x) { return (byte)(x >> 8); }
private static byte short0(short x) { return (byte)(x ); }
static void putShortL(ByteBuffer bb, int bi, short x) {
bb._put(bi , short0(x));
bb._put(bi + 1, short1(x));
}
static void putShortL(long a, short x) {
_put(a , short0(x));
_put(a + 1, short1(x));
}
static void putShortB(ByteBuffer bb, int bi, short x) {
bb._put(bi , short1(x));
bb._put(bi + 1, short0(x));
}
static void putShortB(long a, short x) {
_put(a , short1(x));
_put(a + 1, short0(x));
}
static void putShort(ByteBuffer bb, int bi, short x, boolean bigEndian) {
if (bigEndian)
putShortB(bb, bi, x);
else
putShortL(bb, bi, x);
}
static void putShort(long a, short x, boolean bigEndian) {
if (bigEndian)
putShortB(a, x);
else
putShortL(a, x);
}
// -- get/put int --
static private int makeInt(byte b3, byte b2, byte b1, byte b0) {
return (((b3 ) << 24) |
((b2 & 0xff) << 16) |
((b1 & 0xff) << 8) |
((b0 & 0xff) ));
}
static int getIntL(ByteBuffer bb, int bi) {
return makeInt(bb._get(bi + 3),
bb._get(bi + 2),
bb._get(bi + 1),
bb._get(bi ));
}
static int getIntL(long a) {
return makeInt(_get(a + 3),
_get(a + 2),
_get(a + 1),
_get(a ));
}
static int getIntB(ByteBuffer bb, int bi) {
return makeInt(bb._get(bi ),
bb._get(bi + 1),
bb._get(bi + 2),
bb._get(bi + 3));
}
static int getIntB(long a) {
return makeInt(_get(a ),
_get(a + 1),
_get(a + 2),
_get(a + 3));
}
static int getInt(ByteBuffer bb, int bi, boolean bigEndian) {
return bigEndian ? getIntB(bb, bi) : getIntL(bb, bi) ;
}
static int getInt(long a, boolean bigEndian) {
return bigEndian ? getIntB(a) : getIntL(a) ;
}
private static byte int3(int x) { return (byte)(x >> 24); }
private static byte int2(int x) { return (byte)(x >> 16); }
private static byte int1(int x) { return (byte)(x >> 8); }
private static byte int0(int x) { return (byte)(x ); }
static void putIntL(ByteBuffer bb, int bi, int x) {
bb._put(bi + 3, int3(x));
bb._put(bi + 2, int2(x));
bb._put(bi + 1, int1(x));
bb._put(bi , int0(x));
}
static void putIntL(long a, int x) {
_put(a + 3, int3(x));
_put(a + 2, int2(x));
_put(a + 1, int1(x));
_put(a , int0(x));
}
static void putIntB(ByteBuffer bb, int bi, int x) {
bb._put(bi , int3(x));
bb._put(bi + 1, int2(x));
bb._put(bi + 2, int1(x));
bb._put(bi + 3, int0(x));
}
static void putIntB(long a, int x) {
_put(a , int3(x));
_put(a + 1, int2(x));
_put(a + 2, int1(x));
_put(a + 3, int0(x));
}
static void putInt(ByteBuffer bb, int bi, int x, boolean bigEndian) {
if (bigEndian)
putIntB(bb, bi, x);
else
putIntL(bb, bi, x);
}
static void putInt(long a, int x, boolean bigEndian) {
if (bigEndian)
putIntB(a, x);
else
putIntL(a, x);
}
// -- get/put long --
static private long makeLong(byte b7, byte b6, byte b5, byte b4,
byte b3, byte b2, byte b1, byte b0)
{
return ((((long)b7 ) << 56) |
(((long)b6 & 0xff) << 48) |
(((long)b5 & 0xff) << 40) |
(((long)b4 & 0xff) << 32) |
(((long)b3 & 0xff) << 24) |
(((long)b2 & 0xff) << 16) |
(((long)b1 & 0xff) << 8) |
(((long)b0 & 0xff) ));
}
static long getLongL(ByteBuffer bb, int bi) {
return makeLong(bb._get(bi + 7),
bb._get(bi + 6),
bb._get(bi + 5),
bb._get(bi + 4),
bb._get(bi + 3),
bb._get(bi + 2),
bb._get(bi + 1),
bb._get(bi ));
}
static long getLongL(long a) {
return makeLong(_get(a + 7),
_get(a + 6),
_get(a + 5),
_get(a + 4),
_get(a + 3),
_get(a + 2),
_get(a + 1),
_get(a ));
}
static long getLongB(ByteBuffer bb, int bi) {
return makeLong(bb._get(bi ),
bb._get(bi + 1),
bb._get(bi + 2),
bb._get(bi + 3),
bb._get(bi + 4),
bb._get(bi + 5),
bb._get(bi + 6),
bb._get(bi + 7));
}
static long getLongB(long a) {
return makeLong(_get(a ),
_get(a + 1),
_get(a + 2),
_get(a + 3),
_get(a + 4),
_get(a + 5),
_get(a + 6),
_get(a + 7));
}
static long getLong(ByteBuffer bb, int bi, boolean bigEndian) {
return bigEndian ? getLongB(bb, bi) : getLongL(bb, bi);
}
static long getLong(long a, boolean bigEndian) {
return bigEndian ? getLongB(a) : getLongL(a);
}
private static byte long7(long x) { return (byte)(x >> 56); }
private static byte long6(long x) { return (byte)(x >> 48); }
private static byte long5(long x) { return (byte)(x >> 40); }
private static byte long4(long x) { return (byte)(x >> 32); }
private static byte long3(long x) { return (byte)(x >> 24); }
private static byte long2(long x) { return (byte)(x >> 16); }
private static byte long1(long x) { return (byte)(x >> 8); }
private static byte long0(long x) { return (byte)(x ); }
static void putLongL(ByteBuffer bb, int bi, long x) {
bb._put(bi + 7, long7(x));
bb._put(bi + 6, long6(x));
bb._put(bi + 5, long5(x));
bb._put(bi + 4, long4(x));
bb._put(bi + 3, long3(x));
bb._put(bi + 2, long2(x));
bb._put(bi + 1, long1(x));
bb._put(bi , long0(x));
}
static void putLongL(long a, long x) {
_put(a + 7, long7(x));
_put(a + 6, long6(x));
_put(a + 5, long5(x));
_put(a + 4, long4(x));
_put(a + 3, long3(x));
_put(a + 2, long2(x));
_put(a + 1, long1(x));
_put(a , long0(x));
}
static void putLongB(ByteBuffer bb, int bi, long x) {
bb._put(bi , long7(x));
bb._put(bi + 1, long6(x));
bb._put(bi + 2, long5(x));
bb._put(bi + 3, long4(x));
bb._put(bi + 4, long3(x));
bb._put(bi + 5, long2(x));
bb._put(bi + 6, long1(x));
bb._put(bi + 7, long0(x));
}
static void putLongB(long a, long x) {
_put(a , long7(x));
_put(a + 1, long6(x));
_put(a + 2, long5(x));
_put(a + 3, long4(x));
_put(a + 4, long3(x));
_put(a + 5, long2(x));
_put(a + 6, long1(x));
_put(a + 7, long0(x));
}
static void putLong(ByteBuffer bb, int bi, long x, boolean bigEndian) {
if (bigEndian)
putLongB(bb, bi, x);
else
putLongL(bb, bi, x);
}
static void putLong(long a, long x, boolean bigEndian) {
if (bigEndian)
putLongB(a, x);
else
putLongL(a, x);
}
// -- get/put float --
static float getFloatL(ByteBuffer bb, int bi) {
return Float.intBitsToFloat(getIntL(bb, bi));
}
static float getFloatL(long a) {
return Float.intBitsToFloat(getIntL(a));
}
static float getFloatB(ByteBuffer bb, int bi) {
return Float.intBitsToFloat(getIntB(bb, bi));
}
static float getFloatB(long a) {
return Float.intBitsToFloat(getIntB(a));
}
static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) {
return bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi);
}
static float getFloat(long a, boolean bigEndian) {
return bigEndian ? getFloatB(a) : getFloatL(a);
}
static void putFloatL(ByteBuffer bb, int bi, float x) {
putIntL(bb, bi, Float.floatToRawIntBits(x));
}
static void putFloatL(long a, float x) {
putIntL(a, Float.floatToRawIntBits(x));
}
static void putFloatB(ByteBuffer bb, int bi, float x) {
putIntB(bb, bi, Float.floatToRawIntBits(x));
}
static void putFloatB(long a, float x) {
putIntB(a, Float.floatToRawIntBits(x));
}
static void putFloat(ByteBuffer bb, int bi, float x, boolean bigEndian) {
if (bigEndian)
putFloatB(bb, bi, x);
else
putFloatL(bb, bi, x);
}
static void putFloat(long a, float x, boolean bigEndian) {
if (bigEndian)
putFloatB(a, x);
else
putFloatL(a, x);
}
// -- get/put double --
static double getDoubleL(ByteBuffer bb, int bi) {
return Double.longBitsToDouble(getLongL(bb, bi));
}
static double getDoubleL(long a) {
return Double.longBitsToDouble(getLongL(a));
}
static double getDoubleB(ByteBuffer bb, int bi) {
return Double.longBitsToDouble(getLongB(bb, bi));
}
static double getDoubleB(long a) {
return Double.longBitsToDouble(getLongB(a));
}
static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) {
return bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi);
}
static double getDouble(long a, boolean bigEndian) {
return bigEndian ? getDoubleB(a) : getDoubleL(a);
}
static void putDoubleL(ByteBuffer bb, int bi, double x) {
putLongL(bb, bi, Double.doubleToRawLongBits(x));
}
static void putDoubleL(long a, double x) {
putLongL(a, Double.doubleToRawLongBits(x));
}
static void putDoubleB(ByteBuffer bb, int bi, double x) {
putLongB(bb, bi, Double.doubleToRawLongBits(x));
}
static void putDoubleB(long a, double x) {
putLongB(a, Double.doubleToRawLongBits(x));
}
static void putDouble(ByteBuffer bb, int bi, double x, boolean bigEndian) {
if (bigEndian)
putDoubleB(bb, bi, x);
else
putDoubleL(bb, bi, x);
}
static void putDouble(long a, double x, boolean bigEndian) {
if (bigEndian)
putDoubleB(a, x);
else
putDoubleL(a, x);
}
// -- Unsafe access --
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static byte _get(long a) {
return unsafe.getByte(a);
}
private static void _put(long a, byte b) {
unsafe.putByte(a, b);
}
static Unsafe unsafe() {
return unsafe;
}
// -- Processor and memory-system properties --
private static final ByteOrder 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);
}
}
private static int pageSize = -1;
static int pageSize() {
if (pageSize == -1)
pageSize = unsafe().pageSize();
return pageSize;
}
static int pageCount(long size) {
return (int)(size + (long)pageSize() - 1L) / pageSize();
}
private static boolean unaligned;
private static boolean unalignedKnown = false;
static boolean unaligned() {
if (unalignedKnown)
return unaligned;
String arch = AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("os.arch"));
unaligned = arch.equals("i386") || arch.equals("x86")
|| arch.equals("amd64") || arch.equals("x86_64")
|| arch.equals("ppc64") || arch.equals("ppc64le");
unalignedKnown = true;
return unaligned;
}
// -- Direct memory management --
// A user-settable upper limit on the maximum amount of allocatable
// direct buffer memory. This value may be changed during VM
// initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
private static volatile long maxMemory = VM.maxDirectMemory();
private static final AtomicLong reservedMemory = new AtomicLong();
private static final AtomicLong totalCapacity = new AtomicLong();
private static final AtomicLong count = new AtomicLong();
private static volatile boolean memoryLimitSet = false;
// max. number of sleeps during try-reserving with exponentially
// increasing delay before throwing OutOfMemoryError:
// 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s)
// which means that OOME will be thrown after 0.5 s of trying
private static final int MAX_SLEEPS = 9;
// These methods should be called whenever direct memory is allocated or
// freed. They allow the user to control the amount of direct memory
// which a process may access. All sizes are specified in bytes.
static void reserveMemory(long size, int cap) {
if (!memoryLimitSet && VM.isBooted()) {
maxMemory = VM.maxDirectMemory();
memoryLimitSet = true;
}
// optimist!
if (tryReserveMemory(size, cap)) {
return;
}
final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess();
// retry while helping enqueue pending Reference objects
// which includes executing pending Cleaner(s) which includes
// Cleaner(s) that free direct buffer memory
while (jlra.tryHandlePendingReference()) {
if (tryReserveMemory(size, cap)) {
return;
}
}
// trigger VM's Reference processing
System.gc();
// a retry loop with exponential back-off delays
// (this gives VM some time to do it's job)
boolean interrupted = false;
try {
long sleepTime = 1;
int sleeps = 0;
while (true) {
if (tryReserveMemory(size, cap)) {
return;
}
if (sleeps >= MAX_SLEEPS) {
break;
}
if (!jlra.tryHandlePendingReference()) {
try {
Thread.sleep(sleepTime);
sleepTime <<= 1;
sleeps++;
} catch (InterruptedException e) {
interrupted = true;
}
}
}
// no luck
throw new OutOfMemoryError("Direct buffer memory");
} finally {
if (interrupted) {
// don't swallow interrupts
Thread.currentThread().interrupt();
}
}
}
private static boolean tryReserveMemory(long size, int cap) {
// -XX:MaxDirectMemorySize limits the total capacity rather than the
// actual memory usage, which will differ when buffers are page
// aligned.
long totalCap;
while (cap <= maxMemory - (totalCap = totalCapacity.get())) {
if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) {
reservedMemory.addAndGet(size);
count.incrementAndGet();
return true;
}
}
return false;
}
static void unreserveMemory(long size, int cap) {
long cnt = count.decrementAndGet();
long reservedMem = reservedMemory.addAndGet(-size);
long totalCap = totalCapacity.addAndGet(-cap);
assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0;
}
// -- Monitoring of direct buffer usage --
static {
// setup access to this package in SharedSecrets
sun.misc.SharedSecrets.setJavaNioAccess(
new sun.misc.JavaNioAccess() {
@Override
public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() {
return new sun.misc.JavaNioAccess.BufferPool() {
@Override
public String getName() {
return "direct";
}
@Override
public long getCount() {
return Bits.count.get();
}
@Override
public long getTotalCapacity() {
return Bits.totalCapacity.get();
}
@Override
public long getMemoryUsed() {
return Bits.reservedMemory.get();
}
};
}
@Override
public ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) {
return new DirectByteBuffer(addr, cap, ob);
}
@Override
public void truncate(Buffer buf) {
buf.truncate();
}
});
}
// -- Bulk get/put acceleration --
// 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.
static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6;
static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
// This number limits the number of bytes to copy per call to Unsafe's
// copyMemory method. A limit is imposed to allow for safepoint polling
// during a large copy
static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
// These methods do no bounds checking. Verification that the copy will not
// result in memory corruption should be done prior to invocation.
// All positions and lengths are specified in bytes.
/**
* Copy from given source array to destination address.
*
* @param src
* source array
* @param srcBaseOffset
* offset of first element of storage in source array
* @param srcPos
* offset within source array of the first element to read
* @param dstAddr
* destination address
* @param length
* number of bytes to copy
*/
static void copyFromArray(Object src, long srcBaseOffset, long srcPos,
long dstAddr, long length)
{
long offset = srcBaseOffset + srcPos;
while (length > 0) {
long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
unsafe.copyMemory(src, offset, null, dstAddr, size);
length -= size;
offset += size;
dstAddr += size;
}
}
/**
* Copy from source address into given destination array.
*
* @param srcAddr
* source address
* @param dst
* destination array
* @param dstBaseOffset
* offset of first element of storage in destination array
* @param dstPos
* offset within destination array of the first element to write
* @param length
* number of bytes to copy
*/
static void copyToArray(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;
}
}
/**
* Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
*
* @param src
* the source array, must be a 16-bit primitive array type
* @param srcPos
* byte offset within source array of the first element to read
* @param dstAddr
* destination address
* @param length
* number of bytes to copy
*/
static void copyFromCharArray(Object src, long srcPos, long dstAddr, long length) {
copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
}
/**
* Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
*
* @param srcAddr
* source address
* @param dst
* destination array, must be a 16-bit primitive array type
* @param dstPos
* byte offset within the destination array of the first element to write
* @param length
* number of bytes to copy
*/
static void copyToCharArray(long srcAddr, Object dst, long dstPos, long length) {
copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
}
/**
* Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
*
* @param src
* the source array, must be a 16-bit primitive array type
* @param srcPos
* byte offset within source array of the first element to read
* @param dstAddr
* destination address
* @param length
* number of bytes to copy
*/
static void copyFromShortArray(Object src, long srcPos, long dstAddr, long length) {
copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
}
/**
* Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
*
* @param srcAddr
* source address
* @param dst
* destination array, must be a 16-bit primitive array type
* @param dstPos
* byte offset within the destination array of the first element to write
* @param length
* number of bytes to copy
*/
static void copyToShortArray(long srcAddr, Object dst, long dstPos, long length) {
copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
}
/**
* Copy and unconditionally byte swap 32 bit elements from a heap array to off-heap memory
*
* @param src
* the source array, must be a 32-bit primitive array type
* @param srcPos
* byte offset within source array of the first element to read
* @param dstAddr
* destination address
* @param length
* number of bytes to copy
*/
static void copyFromIntArray(Object src, long srcPos, long dstAddr, long length) {
copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 4);
}
/**
* Copy and unconditionally byte swap 32 bit elements from off-heap memory to a heap array
*
* @param srcAddr
* source address
* @param dst
* destination array, must be a 32-bit primitive array type
* @param dstPos
* byte offset within the destination array of the first element to write
* @param length
* number of bytes to copy
*/
static void copyToIntArray(long srcAddr, Object dst, long dstPos, long length) {
copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 4);
}
/**
* Copy and unconditionally byte swap 64 bit elements from a heap array to off-heap memory
*
* @param src
* the source array, must be a 64-bit primitive array type
* @param srcPos
* byte offset within source array of the first element to read
* @param dstAddr
* destination address
* @param length
* number of bytes to copy
*/
static void copyFromLongArray(Object src, long srcPos, long dstAddr, long length) {
copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 8);
}
/**
* Copy and unconditionally byte swap 64 bit elements from off-heap memory to a heap array
*
* @param srcAddr
* source address
* @param dst
* destination array, must be a 64-bit primitive array type
* @param dstPos
* byte offset within the destination array of the first element to write
* @param length
* number of bytes to copy
*/
static void copyToLongArray(long srcAddr, Object dst, long dstPos, long length) {
copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 8);
}
private static boolean isPrimitiveArray(Class<?> c) {
Class<?> componentType = c.getComponentType();
return componentType != null && componentType.isPrimitive();
}
private native static void copySwapMemory0(Object srcBase, long srcOffset,
Object destBase, long destOffset,
long bytes, long elemSize);
/**
* Copies all elements from one block of memory to another block,
* *unconditionally* byte swapping the elements on the fly.
*
* <p>This method determines each block's base address by means of two parameters,
* and so it provides (in effect) a <em>double-register</em> addressing mode,
* as discussed in {@link sun.misc.Unsafe#getInt(Object,long)}. When the
* object reference is null, the offset supplies an absolute base address.
*
* @since 8u201
*/
private static void copySwapMemory(Object srcBase, long srcOffset,
Object destBase, long destOffset,
long bytes, long elemSize) {
if (bytes < 0) {
throw new IllegalArgumentException();
}
if (elemSize != 2 && elemSize != 4 && elemSize != 8) {
throw new IllegalArgumentException();
}
if (bytes % elemSize != 0) {
throw new IllegalArgumentException();
}
if ((srcBase == null && srcOffset == 0) ||
(destBase == null && destOffset == 0)) {
throw new NullPointerException();
}
// Must be off-heap, or primitive heap arrays
if (srcBase != null && (srcOffset < 0 || !isPrimitiveArray(srcBase.getClass()))) {
throw new IllegalArgumentException();
}
if (destBase != null && (destOffset < 0 || !isPrimitiveArray(destBase.getClass()))) {
throw new IllegalArgumentException();
}
// Sanity check size and offsets on 32-bit platforms. Most
// significant 32 bits must be zero.
if (unsafe.addressSize() == 4 &&
(bytes >>> 32 != 0 || srcOffset >>> 32 != 0 || destOffset >>> 32 != 0)) {
throw new IllegalArgumentException();
}
if (bytes == 0) {
return;
}
copySwapMemory0(srcBase, srcOffset, destBase, destOffset, bytes, elemSize);
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。