diff --git a/.idea/misc.xml b/.idea/misc.xml
index 1b4d85b..d12a090 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -13,7 +13,7 @@
-
+
\ No newline at end of file
diff --git a/src/com/tofvesson/reflection/SafeReflection.java b/src/com/tofvesson/reflection/SafeReflection.java
index b00001f..abd2eed 100644
--- a/src/com/tofvesson/reflection/SafeReflection.java
+++ b/src/com/tofvesson/reflection/SafeReflection.java
@@ -1,12 +1,8 @@
package com.tofvesson.reflection;
import sun.misc.Unsafe;
-import sun.reflect.ConstructorAccessor;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
+import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -20,15 +16,38 @@ public class SafeReflection {
private static final Unsafe unsafe;
+ private static final Method newInstance, aConAccess, gFieldAccess, fieldAccess;
+ private static final Field ro;
+ private static final long override;
static{
Unsafe u = null;
+ Method m = null, m1 = null, m2 = null, m3 = null;
+ Field f = null;
+ long l = 0;
try{
- Field f = Unsafe.class.getDeclaredField("theUnsafe");
+ Class> c;
+ f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
u = (Unsafe) f.get(null);
- }catch(Exception ignored){} // Exception is never thrown
+ m = Class.forName("jdk.internal.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", Object[].class);
+ u.putBoolean(m, l=u.objectFieldOffset(AccessibleObject.class.getDeclaredField("override")), true);
+ m1 = Constructor.class.getDeclaredMethod("acquireConstructorAccessor");
+ m1.setAccessible(true);
+ m2 = Field.class.getDeclaredMethod("getFieldAccessor", Object.class);
+ m2.setAccessible(true);
+ m3 = (c=Class.forName("jdk.internal.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl")).getDeclaredMethod("set", Object.class, Object.class);
+ u.putBoolean(m3, l, true);
+ f = c.getSuperclass().getDeclaredField("isReadOnly");
+ u.putBoolean(f, l, true);
+ }catch(Exception ignored){ ignored.printStackTrace(); } // Exception is never thrown
unsafe = u;
+ newInstance = m;
+ aConAccess = m1;
+ gFieldAccess = m2;
+ fieldAccess = m3;
+ ro = f;
+ override = l;
}
/**
@@ -41,7 +60,7 @@ public class SafeReflection {
public static Constructor getConstructor(Class c, Class>... params){
try{
Constructor c1 = c.getConstructor(params);
- c1.setAccessible(true);
+ unsafe.putBoolean(c1, override, true);
return c1;
}catch(Exception e){}
return null;
@@ -57,7 +76,7 @@ public class SafeReflection {
try {
@SuppressWarnings("unchecked")
Constructor c1 = (Constructor) c.getDeclaredConstructors()[0];
- c1.setAccessible(true);
+ unsafe.putBoolean(c1, override, true);
return c1;
}catch (Exception e){}
return null;
@@ -74,7 +93,7 @@ public class SafeReflection {
public static Method getMethod(Class> c, String name, Class>... params){
try{
Method m = c.getDeclaredMethod(name, params);
- m.setAccessible(true);
+ unsafe.putBoolean(m, override, true);
return m;
}catch(Exception e){}
return null;
@@ -99,7 +118,7 @@ public class SafeReflection {
* @return Return value of method or null if method is null.
*/
public static Object invokeMethod(Object inst, Method m, Object... params){
- if(m!=null) m.setAccessible(true);
+ if(m!=null) unsafe.putBoolean(m, override, true);
try{ return m!=null?m.invoke(inst, params):null; }catch(Exception e){}
return null;
}
@@ -115,7 +134,7 @@ public class SafeReflection {
public static Method getFirstMethod(Class> c, String name){
try{
Method[] m = c.getDeclaredMethods();
- for (Method aM : m) if(aM.getName().equals(name)){ aM.setAccessible(true); return aM;}
+ for (Method aM : m) if(aM.getName().equals(name)){ unsafe.putBoolean(aM, override, true); return aM;}
}catch(Exception e){}
return null;
}
@@ -129,7 +148,7 @@ public class SafeReflection {
public static Field getField(Class> c, String name){
try{
Field f = c.getDeclaredField(name);
- f.setAccessible(true);
+ unsafe.putBoolean(f, override, true);
return f;
}catch(Exception e){}
return null;
@@ -167,7 +186,7 @@ public class SafeReflection {
public static Object getEnclosingClassObjectRef(Object nested){
try{
Field f = nested.getClass().getDeclaredField("this$0");
- f.setAccessible(true);
+ unsafe.putBoolean(f, override, true);
return f.get(nested);
}catch(Exception e){}
return null;
@@ -200,7 +219,7 @@ public class SafeReflection {
try {
// Get a reference to the static method values() and get values
Method v = clazz.getDeclaredMethod("values");
- v.setAccessible(true);
+ unsafe.putBoolean(v, override, true);
T[] values = (T[]) v.invoke(null);
// Return object if it already exists
@@ -215,12 +234,10 @@ public class SafeReflection {
// Get enum constructor (inherited from Enum.class)
Constructor c = clazz.getDeclaredConstructor(paramList);
- c.setAccessible(true);
- Method m = Constructor.class.getDeclaredMethod("acquireConstructorAccessor");
- m.setAccessible(true);
+ unsafe.putBoolean(c, override, true);
// Get constructor accessor since Constructor.newInstance throws an exception because Enums are "immutable"
- ConstructorAccessor access = (ConstructorAccessor) m.invoke(c);
+ Object access = aConAccess.invoke(c);
Object[] parameters = new Object[def.params.size()+2];
parameters[0] = name;
@@ -229,7 +246,7 @@ public class SafeReflection {
for(Object o : def.params.keySet()) parameters[--iterator] = o;
// Create new instance of enum with valid name and ordinal
- u = (T) access.newInstance(parameters);
+ u = (T) newInstance.invoke(access, (Object) parameters);
// Get the final name field from Enum.class and make it temporarily modifiable
Field f = Enum.class.getDeclaredField("name");
@@ -249,22 +266,17 @@ public class SafeReflection {
// Start doing magic by getting an instance of sun.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl.class
// Class is package-local so we can't reference it by anything other than Object
- m = Field.class.getDeclaredMethod("getFieldAccessor", Object.class);
- m.setAccessible(true);
- Object UQSOFAImpl = m.invoke(f, u);
+ Object UQSOFAImpl = gFieldAccess.invoke(f, u);
// Get "isReadOnly" flag ($VALUES is always read-only even if Field.setAccessible(true) is called)
// Flag is located in superclass (sun.reflect.UnsafeQualifiedStaticFieldAccessorImpl.class (also fucking package-local))
// Set flag to 'false' to allow for modification against Java's will
- Field f1 = UQSOFAImpl.getClass().getSuperclass().getDeclaredField("isReadOnly");
- f1.setAccessible(true);
- f1.setBoolean(UQSOFAImpl, false);
+ ro.setBoolean(UQSOFAImpl, false);
// Invoke set() method on UnsafeQualifiedStaticObjectFieldAccessorImpl object which sets the
// private field $VALUES to our new array
- m = UQSOFAImpl.getClass().getDeclaredMethod("set", Object.class, Object.class);
- m.setAccessible(true);
- m.invoke(UQSOFAImpl, f, $VALUES);
+ System.out.println(UQSOFAImpl.getClass());
+ fieldAccess.invoke(UQSOFAImpl, f, $VALUES);
} catch (Exception wrongParams) { throw new RuntimeException(wrongParams); }
return u;
}
@@ -284,9 +296,12 @@ public class SafeReflection {
/**
* A definition for custom enum creation.
*/
- public static class EnumDefinition {
+ public static final class EnumDefinition {
HashMap