JAVA_9 {
final class ReferencedUnsafe
{
- private final Object sunMiscUnsafeTheUnsafe;
+ private final SecurityActions.TheUnsafe sunMiscUnsafeTheUnsafe;
private final MethodHandle defineClass;
- ReferencedUnsafe(Object usf, MethodHandle meth)
+ ReferencedUnsafe(SecurityActions.TheUnsafe usf, MethodHandle meth)
{
this.sunMiscUnsafeTheUnsafe = usf;
this.defineClass = meth;
throw new IllegalAccessError("Access denied for caller.");
try {
return (Class<?>) defineClass.invokeWithArguments(
- sunMiscUnsafeTheUnsafe,
+ sunMiscUnsafeTheUnsafe.theUnsafe,
name, b, off, len, loader, protectionDomain);
} catch (Throwable e) {
if (e instanceof RuntimeException) throw (RuntimeException) e;
&& stack.getCallerClass() != this.getClass())
throw new IllegalAccessError("Access denied for caller.");
try {
- Object usf = SecurityActions.getSunMiscUnsafeAnonymously();
- MethodHandle meth = SecurityActions.getMethodHandle(ClassLoader.class,
- "defineClass", new Class[] {
- String.class, byte[].class, int.class, int.class,
- ProtectionDomain.class
- });
+ SecurityActions.TheUnsafe usf = SecurityActions.getSunMiscUnsafeAnonymously();
+ MethodHandle meth = MethodHandles.lookup()
+ .unreflect(usf.methods.get("defineClass").get(0));
return new ReferencedUnsafe(usf, meth);
} catch (Throwable e) {
throw new RuntimeException("cannot initialize", e);
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javassist.bytecode.ClassFile;
+
class SecurityActions extends SecurityManager
{
public static final SecurityActions stack = new SecurityActions();
}
}
- static Object getSunMiscUnsafeAnonymously() throws ClassNotFoundException
+ static TheUnsafe getSunMiscUnsafeAnonymously() throws ClassNotFoundException
{
try {
return AccessController.doPrivileged(
- new PrivilegedExceptionAction<Object>() { public Object run() throws
+ new PrivilegedExceptionAction<TheUnsafe>() { public TheUnsafe run() throws
ClassNotFoundException, NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException {
Class<?> unsafe = Class.forName("sun.misc.Unsafe");
Field theUnsafe = unsafe.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
- Object usf = theUnsafe.get(null);
+ TheUnsafe usf = stack.new TheUnsafe(unsafe, theUnsafe.get(null));
theUnsafe.setAccessible(false);
+ disableWarning(usf);
return usf;
}
});
throw new RuntimeException(e.getCause());
}
}
+ class TheUnsafe
+ {
+ final Class<?> unsafe;
+ final Object theUnsafe;
+ final Map<String, List<Method>> methods =
+ new HashMap<String, List<Method>>();
+
+ TheUnsafe(Class<?> c, Object o)
+ {
+ this.unsafe = c;
+ this.theUnsafe = o;
+ for (Method m: unsafe.getDeclaredMethods()) {
+ if (!methods.containsKey(m.getName())) {
+ methods.put(m.getName(), Collections.singletonList(m));
+ continue;
+ }
+ if (methods.get(m.getName()).size() == 1)
+ methods.put(m.getName(),
+ new ArrayList<Method>(methods.get(m.getName())));
+ methods.get(m.getName()).add(m);
+ }
+ }
+
+ private Method getM(String name, Object[] o)
+ {
+ return methods.get(name).get(0);
+ }
+
+ public Object call(String name, Object... args)
+ {
+ try {
+ return getM(name, args).invoke(theUnsafe, args);
+ } catch (Throwable t) {t.printStackTrace();}
+ return null;
+ }
+ }
+ static void disableWarning(TheUnsafe tu) {
+ try {
+ if (ClassFile.MAJOR_VERSION < ClassFile.JAVA_9)
+ return;
+ Class<?> cls = Class.forName("jdk.internal.module.IllegalAccessLogger");
+ Field logger = cls.getDeclaredField("logger");
+ tu.call("putObjectVolatile", cls, tu.call("staticFieldOffset", logger), null);
+ } catch (Exception e) { /*swallow*/ }
+ }
}
+