28import java.lang.reflect.Field;
29import java.lang.reflect.InvocationTargetException;
30import java.lang.reflect.Method;
31import java.nio.ByteBuffer;
32import java.security.PrivilegedAction;
34import org.jau.sec.SecurityUtil;
35import org.jau.sys.Debug;
36import org.jau.sys.PlatformProps;
43 static final boolean DEBUG;
50 private static final Object theUnsafe;
51 private static final Method unsafeCleanBB;
52 private static volatile boolean hasUnsafeCleanBBError;
54 private static final Method staticFieldOffset;
55 private static final Method getObjectVolatile;
56 private static final Method putObjectVolatile;
57 private static volatile boolean hasGetPutObjectVolatile;
59 private static final Class<?> illegalAccessLoggerClass;
60 private static final Long illegalAccessLoggerOffset;
61 private static final Object illegalAccessLoggerSync =
new Object();
62 private static volatile boolean hasIllegalAccessError;
65 final Object[] _theUnsafe = {
null };
66 final Method[] _cleanBB = {
null };
67 final Method[] _staticFieldOffset = {
null };
68 final Method[] _objectVolatile = {
null,
null };
69 final Class<?>[] _illegalAccessLoggerClass = {
null };
70 final Long[] _loggerOffset = {
null };
72 SecurityUtil.doPrivileged(
new PrivilegedAction<Object>() {
75 Class<?> unsafeClass =
null;
78 unsafeClass = Class.forName(
"sun.misc.Unsafe");
80 final Field f = unsafeClass.getDeclaredField(
"theUnsafe");
81 f.setAccessible(
true);
82 _theUnsafe[0] = f.get(
null);
84 _cleanBB[0] = unsafeClass.getMethod(
"invokeCleaner", java.nio.ByteBuffer.class);
85 _cleanBB[0].setAccessible(
true);
86 }
catch(
final Throwable t) {
88 ExceptionUtils.dumpThrowable(
"UnsafeUtil", t);
91 if(
null != _theUnsafe[0] && PlatformProps.JAVA_9 ) {
93 _staticFieldOffset[0] = unsafeClass.getDeclaredMethod(
"staticFieldOffset", Field.class);
94 _objectVolatile[0] = unsafeClass.getDeclaredMethod(
"getObjectVolatile", Object.class,
long.class);
95 _objectVolatile[1] = unsafeClass.getDeclaredMethod(
"putObjectVolatile", Object.class,
long.class, Object.class);
97 if( PlatformProps.JAVA_9 ) {
98 _illegalAccessLoggerClass[0] = Class.forName(
"jdk.internal.module.IllegalAccessLogger");
99 final Field loggerField = _illegalAccessLoggerClass[0].getDeclaredField(
"logger");
100 _loggerOffset[0] = (Long) _staticFieldOffset[0].invoke(_theUnsafe[0], loggerField);
102 }
catch(
final Throwable t) {
104 ExceptionUtils.dumpThrowable(
"UnsafeUtil", t);
110 theUnsafe = _theUnsafe[0];
111 unsafeCleanBB = _cleanBB[0];
112 hasUnsafeCleanBBError =
null == theUnsafe ||
null == unsafeCleanBB;
114 System.err.println(
"UnsafeUtil.init: hasTheUnsafe: "+(
null!=theUnsafe)+
", hasInvokeCleaner: "+!hasUnsafeCleanBBError);
117 staticFieldOffset = _staticFieldOffset[0];
118 getObjectVolatile = _objectVolatile[0];
119 putObjectVolatile = _objectVolatile[1];
120 hasGetPutObjectVolatile =
null != staticFieldOffset &&
null != getObjectVolatile &&
null != putObjectVolatile;
121 illegalAccessLoggerClass = _illegalAccessLoggerClass[0];
122 illegalAccessLoggerOffset = _loggerOffset[0];
123 hasIllegalAccessError = !hasGetPutObjectVolatile ||
null == illegalAccessLoggerClass ||
null == illegalAccessLoggerOffset;
125 System.err.println(
"UnsafeUtil.init: hasUnsafeGetPutObjectVolatile: "+hasGetPutObjectVolatile+
", hasUnsafeIllegalAccessLogger: "+!hasIllegalAccessError);
146 if( hasUnsafeCleanBBError || !bb.isDirect() ) {
150 unsafeCleanBB.invoke(theUnsafe, bb);
152 }
catch(
final Throwable t) {
153 hasUnsafeCleanBBError =
true;
182 if( !hasIllegalAccessError ) {
183 synchronized(illegalAccessLoggerSync) {
184 final Object newLogger =
null;
185 Object oldLogger =
null;
187 oldLogger = getObjectVolatile.invoke(theUnsafe, illegalAccessLoggerClass, illegalAccessLoggerOffset);
188 putObjectVolatile.invoke(theUnsafe, illegalAccessLoggerClass, illegalAccessLoggerOffset, newLogger);
189 }
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
191 hasIllegalAccessError =
true;
199 }
catch (
final Throwable t) {
203 throw new RuntimeException(t);
206 putObjectVolatile.invoke(theUnsafe, illegalAccessLoggerClass, illegalAccessLoggerOffset, oldLogger);
207 }
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
209 hasIllegalAccessError =
true;
210 throw new InternalError(e);
static void dumpThrowable(final String additionalDescr, final Throwable t)
Dumps a Throwable to System.err in a decorating message including the current thread name,...
Utility methods allowing easy access to certain sun.misc.Unsafe functionality.
static boolean hasInvokeCleaner()
Returns true if sun.misc.Unsafe.invokeCleaner(java.nio.ByteBuffer) is available and has not caused an...
static< T > T doWithoutIllegalAccessLogger(final PrivilegedAction< T > action)
Issue the given user action while jdk.internal.module.IllegalAcessLogger's logger has been temporaril...
static boolean hasIllegalAccessLoggerAccess()
Returns true if access to jdk.internal.module.IllegalAcessLogger's logger field is available and has ...
static boolean invokeCleaner(final ByteBuffer bb)
Access to sun.misc.Unsafe.invokeCleaner(java.nio.ByteBuffer).
Helper routines for logging and debugging.
static final boolean debug(final String subcomponent)