package io.gatling.jsonbenchmark.util;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
/**
* Inspired from Netty's PlatformDependant0
* @author slandelle
*/
public final class UnsafeUtil {
public static final Unsafe UNSAFE;
public static final long STRING_VALUE_FIELD_OFFSET;
public static final long STRING_OFFSET_FIELD_OFFSET;
public static final long STRING_COUNT_FIELD_OFFSET;
static {
Unsafe unsafe;
try {
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
unsafe = (Unsafe) unsafeField.get(null);
} catch (Throwable cause) {
unsafe = null;
}
long stringValueFieldOffset = -1L;
long stringOffsetFieldOffset = -1L;
long stringCountFieldOffset = -1L;
if (unsafe != null) {
try {
stringValueFieldOffset = unsafe.objectFieldOffset(String.class.getDeclaredField("value"));
stringOffsetFieldOffset = unsafe.objectFieldOffset(String.class.getDeclaredField("offset"));
stringCountFieldOffset = unsafe.objectFieldOffset(String.class.getDeclaredField("count"));
} catch (Throwable cause) {
}
}
UNSAFE = unsafe;
STRING_VALUE_FIELD_OFFSET = stringValueFieldOffset;
STRING_OFFSET_FIELD_OFFSET = stringOffsetFieldOffset;
STRING_COUNT_FIELD_OFFSET = stringCountFieldOffset;
}
public static boolean hasUnsafe() {
return UNSAFE != null;
}
public static char[] getChars(String string) {
if (UNSAFE != null) {
char[] value = (char[]) UNSAFE.getObject(string, STRING_VALUE_FIELD_OFFSET);
if (STRING_OFFSET_FIELD_OFFSET != -1) {
// old String version with offset and count
int offset = (int) UNSAFE.getObject(string, STRING_OFFSET_FIELD_OFFSET);
int count = (int) UNSAFE.getObject(string, STRING_COUNT_FIELD_OFFSET);
if (offset == 0 && count == value.length) {
// no need to copy
return value;
} else {
char result[] = new char[count];
System.arraycopy(value, offset, result, 0, count);
return result;
}
} else {
return value;
}
} else {
return string.toCharArray();
}
}
}