aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornickl- <github@jigsoft.co.za>2017-10-27 08:10:22 +0200
committernickl- <github@jigsoft.co.za>2017-11-12 23:49:21 +0200
commit50dd54dc0552960c80aacded54a9ff7fe0f747f6 (patch)
treed890ab52e5b95b94b5696a9c8ce6f576d1c8824a
parentaf399dbfa005ccde16247b88159cc269e243fb22 (diff)
downloadjavassist-50dd54dc0552960c80aacded54a9ff7fe0f747f6.tar.gz
javassist-50dd54dc0552960c80aacded54a9ff7fe0f747f6.zip
Even now Oracle still not happy.
Runtime still throws warnings illegal actions even after all that, there's just no logic to it. We can use Unsafe but don't touch setAccessible. O well might as well enjoy Unsafe while we still can. Wrapped the Unsafe and added method cache with varargs method for invoke calls. Can still do a lot with it but it does what it needs to for now.
-rw-r--r--src/main/javassist/util/proxy/DefineClassHelper.java15
-rwxr-xr-xsrc/main/javassist/util/proxy/SecurityActions.java61
2 files changed, 64 insertions, 12 deletions
diff --git a/src/main/javassist/util/proxy/DefineClassHelper.java b/src/main/javassist/util/proxy/DefineClassHelper.java
index aebb5acb..3ed261e5 100644
--- a/src/main/javassist/util/proxy/DefineClassHelper.java
+++ b/src/main/javassist/util/proxy/DefineClassHelper.java
@@ -38,10 +38,10 @@ public class DefineClassHelper
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;
@@ -54,7 +54,7 @@ public class DefineClassHelper
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;
@@ -72,12 +72,9 @@ public class DefineClassHelper
&& 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);
diff --git a/src/main/javassist/util/proxy/SecurityActions.java b/src/main/javassist/util/proxy/SecurityActions.java
index 4bc10a8a..574073d0 100755
--- a/src/main/javassist/util/proxy/SecurityActions.java
+++ b/src/main/javassist/util/proxy/SecurityActions.java
@@ -25,6 +25,14 @@ import java.security.AccessController;
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();
@@ -170,18 +178,19 @@ class SecurityActions extends SecurityManager
}
}
- 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;
}
});
@@ -198,4 +207,50 @@ class SecurityActions extends SecurityManager
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*/ }
+ }
}
+