com.facebook.presto.hive.$internal.jodd.util.UnsafeUtil Maven / Gradle / Ivy
// Copyright (c) 2003-2014, Jodd Team (com.facebook.presto.hive.$internal.jodd.org). All Rights Reserved.
package com.facebook.presto.hive.$internal.jodd.util;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
/**
* Few methods using infamous java.misc.Unsafe
, mostly for private use.
* See: http://mishadoff.github.io/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/
*
* Thanx to Gatling (http://gatling-tool.org)!
*/
public class UnsafeUtil {
public static final Unsafe UNSAFE;
private static final long STRING_VALUE_FIELD_OFFSET;
private static final long STRING_OFFSET_FIELD_OFFSET;
private 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 ignore) {
unsafe = null;
}
long stringValueFieldOffset = -1L;
long stringOffsetFieldOffset = -1L;
long stringCountFieldOffset = -1L;
if (unsafe != null) {
try {
// this should be:
stringValueFieldOffset = unsafe.objectFieldOffset(String.class.getDeclaredField("value"));
// try also:
stringOffsetFieldOffset = unsafe.objectFieldOffset(String.class.getDeclaredField("offset"));
stringCountFieldOffset = unsafe.objectFieldOffset(String.class.getDeclaredField("count"));
} catch (Throwable ignore) {
}
}
UNSAFE = unsafe;
STRING_VALUE_FIELD_OFFSET = stringValueFieldOffset;
STRING_OFFSET_FIELD_OFFSET = stringOffsetFieldOffset;
STRING_COUNT_FIELD_OFFSET = stringCountFieldOffset;
}
/**
* Returns String characters in most performing way.
* If possible, the inner char[]
will be returned.
* If not, toCharArray()
will be called.
*/
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 = UNSAFE.getInt(string, STRING_OFFSET_FIELD_OFFSET);
int count = UNSAFE.getInt(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();
}
}
/**
* Creates mutable strings from given char array.
*/
public static String createMutableString(char[] chars) {
if (UNSAFE == null) {
return null;
}
String mutable = new String();
UNSAFE.putObject(mutable, STRING_VALUE_FIELD_OFFSET, chars);
if (STRING_COUNT_FIELD_OFFSET != -1) {
UNSAFE.putInt(mutable, STRING_COUNT_FIELD_OFFSET, chars.length);
}
return mutable;
}
}