com.esotericsoftware.kryo.util.UnsafeUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spark-core Show documentation
Show all versions of spark-core Show documentation
Shaded version of Apache Spark 2.x.x for Presto
The newest version!
/* Copyright (c) 2008, Nathan Sweet
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
* - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
package com.esotericsoftware.kryo.util;
import static com.esotericsoftware.minlog.Log.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import sun.misc.Cleaner;
import sun.misc.Unsafe;
import sun.nio.ch.DirectBuffer;
/** A few utility methods for using @link{sun.misc.Unsafe}, mostly for private use.
*
* Use of Unsafe on Android is forbidden, as Android provides only a very limited functionality for this class compared to the JDK
* version.
*
* @author Roman Levenstein */
public class UnsafeUtil {
final static private Unsafe _unsafe;
final static public long byteArrayBaseOffset;
final static public long floatArrayBaseOffset;
final static public long doubleArrayBaseOffset;
final static public long intArrayBaseOffset;
final static public long longArrayBaseOffset;
final static public long shortArrayBaseOffset;
final static public long charArrayBaseOffset;
// Constructor to be used for creation of ByteBuffers that use preallocated memory regions
static Constructor extends ByteBuffer> directByteBufferConstr;
static {
Unsafe tmpUnsafe = null;
long tmpByteArrayBaseOffset = 0;
long tmpFloatArrayBaseOffset = 0;
long tmpDoubleArrayBaseOffset = 0;
long tmpIntArrayBaseOffset = 0;
long tmpLongArrayBaseOffset = 0;
long tmpShortArrayBaseOffset = 0;
long tmpCharArrayBaseOffset = 0;
try {
if (!Util.IS_ANDROID) {
java.lang.reflect.Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
tmpUnsafe = (sun.misc.Unsafe)field.get(null);
tmpByteArrayBaseOffset = tmpUnsafe.arrayBaseOffset(byte[].class);
tmpCharArrayBaseOffset = tmpUnsafe.arrayBaseOffset(char[].class);
tmpShortArrayBaseOffset = tmpUnsafe.arrayBaseOffset(short[].class);
tmpIntArrayBaseOffset = tmpUnsafe.arrayBaseOffset(int[].class);
tmpFloatArrayBaseOffset = tmpUnsafe.arrayBaseOffset(float[].class);
tmpLongArrayBaseOffset = tmpUnsafe.arrayBaseOffset(long[].class);
tmpDoubleArrayBaseOffset = tmpUnsafe.arrayBaseOffset(double[].class);
} else {
if (TRACE) trace("kryo", "Running on Android platform. Use of sun.misc.Unsafe should be disabled");
}
} catch (java.lang.Exception e) {
if (TRACE)
trace("kryo", "sun.misc.Unsafe is not accessible or not available. Use of sun.misc.Unsafe should be disabled");
}
byteArrayBaseOffset = tmpByteArrayBaseOffset;
charArrayBaseOffset = tmpCharArrayBaseOffset;
shortArrayBaseOffset = tmpShortArrayBaseOffset;
intArrayBaseOffset = tmpIntArrayBaseOffset;
floatArrayBaseOffset = tmpFloatArrayBaseOffset;
longArrayBaseOffset = tmpLongArrayBaseOffset;
doubleArrayBaseOffset = tmpDoubleArrayBaseOffset;
_unsafe = tmpUnsafe;
}
static {
ByteBuffer buf = ByteBuffer.allocateDirect(1);
try {
directByteBufferConstr = buf.getClass().getDeclaredConstructor(long.class, int.class, Object.class);
directByteBufferConstr.setAccessible(true);
} catch (Exception e) {
directByteBufferConstr = null;
}
}
/*** Return the sun.misc.Unsafe object. If null is returned, no further Unsafe-related methods are allowed to be invoked from
* UnsafeUtil.
*
* @return instance of sun.misc.Unsafe or null, if this class is not available or not accessible */
final static public Unsafe unsafe () {
return _unsafe;
}
/*** Sort the set of lists by their offsets from the object start address.
*
* @param allFields set of fields to be sorted by their offsets */
public static Field[] sortFieldsByOffset (List allFields) {
Field[] allFieldsArray = allFields.toArray(new Field[] {});
Comparator fieldOffsetComparator = new Comparator() {
@Override
public int compare (Field f1, Field f2) {
long offset1 = unsafe().objectFieldOffset(f1);
long offset2 = unsafe().objectFieldOffset(f2);
if (offset1 < offset2) return -1;
if (offset1 == offset2) return 0;
return 1;
}
};
Arrays.sort(allFieldsArray, fieldOffsetComparator);
for (Field f : allFields) {
if (TRACE) trace("kryo", "Field '" + f.getName() + "' at offset " + unsafe().objectFieldOffset(f));
}
return allFieldsArray;
}
/*** Create a ByteBuffer that uses a provided (off-heap) memory region instead of allocating a new one.
*
* @param address address of the memory region to be used for a ByteBuffer
* @param size size of the memory region
* @return a new ByteBuffer that uses a provided memory region instead of allocating a new one */
final static public ByteBuffer getDirectBufferAt (long address, int size) {
if (directByteBufferConstr == null) return null;
try {
return directByteBufferConstr.newInstance(address, size, null);
} catch (Exception e) {
throw new RuntimeException("Cannot allocate ByteBuffer at a given address: " + address, e);
}
}
/*** Release a direct buffer.
*
* NOTE: If Cleaner is not accessible due to SecurityManager restrictions, reflection could be used to obtain the "clean"
* method and then invoke it. */
static public void releaseBuffer (ByteBuffer niobuffer) {
if (niobuffer != null && niobuffer.isDirect()) {
Object cleaner = ((DirectBuffer)niobuffer).cleaner();
if (cleaner != null) ((Cleaner)cleaner).clean();
niobuffer = null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy