![JAR search and dependency download from the Maven repository](/logo.png)
xdean.jex.util.lang.UnsafeUtil Maven / Gradle / Ivy
The newest version!
package xdean.jex.util.lang;
import static xdean.jex.util.lang.ExceptionUtil.uncheck;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.stream.Stream;
import sun.misc.Unsafe;
import xdean.jex.log.Log;
import xdean.jex.log.LogFactory;
import xdean.jex.util.reflect.ReflectUtil;
public class UnsafeUtil {
private static final Unsafe THE_UNSAFE = initUnsafe();
private static final int ADDRESS_SIZE = THE_UNSAFE.addressSize();
private static final long HEADER_SIZE = initHeaderSize();
private static final boolean useCompressedOops = initUseCompressedOops();
private static final Log LOGGER = LogFactory.from(UnsafeUtil.class);
static {
LOGGER.trace("address size: {0}", ADDRESS_SIZE);
LOGGER.trace("header size: {0}", HEADER_SIZE);
LOGGER.trace("useCompressedOops: {0}", useCompressedOops);
}
public static Unsafe getUnsafe() {
return THE_UNSAFE;
}
/**
* Get the memory address of the given object.
*
* @param o
* @return
*/
public static long addressOf(Object o) {
Object[] array = new Object[] { o };
long baseOffset = THE_UNSAFE.arrayBaseOffset(Object[].class);
long objectAddress;
switch (ADDRESS_SIZE) {
case 4:
objectAddress = THE_UNSAFE.getInt(array, baseOffset);
break;
case 8:
objectAddress = THE_UNSAFE.getLong(array, baseOffset);
break;
default:
throw new IllegalStateException("unsupported address size: " + ADDRESS_SIZE);
}
return objectAddress;
}
/**
* Measure the SHALLOW size of the given class's instance.
* If given an array class, only return the base offset (size of array of length 0).
* For array class, use {@link UnsafeUtil#shallowSizeOf(Object)}.
*
* @param clz
* @return
*/
public static long shallowSizeOf(Class> clz) {
if (PrimitiveTypeUtil.isPrimitive(clz)) {
return PrimitiveTypeUtil.sizeOf(clz);
} else if (clz.isArray()) {
return THE_UNSAFE.arrayBaseOffset(clz);
} else {
long maxOffset = 0L;
Field maxField = null;
for (Field field : ReflectUtil.getAllFields(clz, false)) {
long offset = THE_UNSAFE.objectFieldOffset(field);
if (offset > maxOffset) {
maxOffset = offset;
maxField = field;
}
}
if (maxOffset == 0) {
maxOffset = HEADER_SIZE;
} else if (maxOffset < HEADER_SIZE) {
throw new IllegalStateException("Can't calculate " + clz + "'s size.");
} else {
maxOffset += refSizeOf(maxField.getType());
}
return regulateSize(maxOffset);
}
}
/**
* SHALLOW size of the given object.
* If given a primitive type, the result will be incorrect.
* For primitive type, use {@link UnsafeUtil#shallowSizeOf(Class)}.
*
* @param o
* @return
*/
public static long shallowSizeOf(Object o) {
Class extends Object> clz = o.getClass();
if (clz.isArray()) {
int len = Array.getLength(o);
return regulateSize(THE_UNSAFE.arrayBaseOffset(clz) + THE_UNSAFE.arrayIndexScale(clz) * len);
}
return shallowSizeOf(clz);
}
/**
* HEAP size of the given object.
* If given a primitive type, the result will be incorrect because auto-box.
* For primitive type, use {@link UnsafeUtil#shallowSizeOf(Class)}.
*
* @param o
* @return
*/
public static long sizeOf(Object o) {
return sizeOf(o, new IdentityHashMap<>());
}
private static long sizeOf(Object o, Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy