This commit is contained in:
YuTian 2024-08-08 01:15:40 +08:00
parent 9101db3075
commit 9b37d2a330
2 changed files with 138 additions and 1 deletions

View File

@ -3,7 +3,10 @@ package com.io.yutian.elementoriginlib.util;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import sun.misc.Unsafe; import sun.misc.Unsafe;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
@ -178,4 +181,138 @@ public class ReflectionUtil {
} }
} }
private static Field MODIFIERS_FIELD;
private static Object UNSAFE;
private static MethodHandle UNSAFE_FIELD_OFFSET;
private static MethodHandle UNSAFE_PUT_BOOLEAN;
private static MethodHandle UNSAFE_PUT_DOUBLE;
private static MethodHandle UNSAFE_PUT_FLOAT;
private static MethodHandle UNSAFE_PUT_INT;
private static MethodHandle UNSAFE_PUT_LONG;
private static MethodHandle UNSAFE_PUT_OBJECT;
private static MethodHandle UNSAFE_STATIC_FIELD_OFFSET;
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
public static MethodHandle getFieldGetter(Class<?> clazz, String name) {
return getField(clazz, name, true);
}
public static MethodHandle getFieldSetter(Class<?> clazz, String name) {
return getField(clazz, name, false);
}
public static MethodHandle getField(Class<?> clazz, String name, boolean isGetter) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
if (isGetter) return LOOKUP.unreflectGetter(field);
return LOOKUP.unreflectSetter(field);
} catch (ReflectiveOperationException exception) {
exception.printStackTrace();
return null;
}
}
public static Field getField(Class<?> clazz, String field) {
if (clazz == null)
return null;
Field f = null;
try {
f = clazz.getDeclaredField(field);
f.setAccessible(true);
return f;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Method getMethod(Class<?> clazz, String method, Class<?>... params) {
if (clazz == null)
return null;
Method f = null;
try {
f = clazz.getDeclaredMethod(method, params);
f.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
return f;
}
public static MethodHandle getMethodHandle(Class<?> clazz, String method, Class<?>... params) {
if (clazz == null)
return null;
try {
return LOOKUP.unreflect(getMethod(clazz, method, params));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static MethodHandle getFinalSetter(Class<?> clazz, String field) {
return getFinalSetter(getField(clazz, field));
}
public static MethodHandle getFinalSetter(Field field) {
if (field == null)
return null;
if (MODIFIERS_FIELD == null) {
if (UNSAFE == null) {
try {
UNSAFE = getField(Class.forName("sun.misc.Unsafe"), "theUnsafe").get(null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
UNSAFE_STATIC_FIELD_OFFSET = getMethodHandle(UNSAFE.getClass(), "staticFieldOffset", Field.class)
.bindTo(UNSAFE);
UNSAFE_FIELD_OFFSET = getMethodHandle(UNSAFE.getClass(), "objectFieldOffset", Field.class)
.bindTo(UNSAFE);
UNSAFE_PUT_OBJECT = getMethodHandle(UNSAFE.getClass(), "putObject", Object.class, long.class,
Object.class).bindTo(UNSAFE);
UNSAFE_PUT_INT = getMethodHandle(UNSAFE.getClass(), "putInt", Object.class, long.class, int.class)
.bindTo(UNSAFE);
UNSAFE_PUT_FLOAT = getMethodHandle(UNSAFE.getClass(), "putFloat", Object.class, long.class,
float.class).bindTo(UNSAFE);
UNSAFE_PUT_DOUBLE = getMethodHandle(UNSAFE.getClass(), "putDouble", Object.class, long.class,
double.class).bindTo(UNSAFE);
UNSAFE_PUT_BOOLEAN = getMethodHandle(UNSAFE.getClass(), "putBoolean", Object.class, long.class,
boolean.class).bindTo(UNSAFE);
UNSAFE_PUT_LONG = getMethodHandle(UNSAFE.getClass(), "putLong", Object.class, long.class,
long.class).bindTo(UNSAFE);
}
try {
boolean isStatic = Modifier.isStatic(field.getModifiers());
long offset = (long) (isStatic ? UNSAFE_STATIC_FIELD_OFFSET.invoke(field)
: UNSAFE_FIELD_OFFSET.invoke(field));
MethodHandle mh = field.getType() == int.class ? UNSAFE_PUT_INT
: field.getType() == boolean.class ? UNSAFE_PUT_BOOLEAN
: field.getType() == double.class ? UNSAFE_PUT_DOUBLE
: field.getType() == float.class ? UNSAFE_PUT_FLOAT
: field.getType() == long.class ? UNSAFE_PUT_LONG : UNSAFE_PUT_OBJECT;
return isStatic ? MethodHandles.insertArguments(mh, 0, field.getDeclaringClass(), offset)
: MethodHandles.insertArguments(mh, 1, offset);
} catch (Throwable t) {
t.printStackTrace();
return null;
}
}
try {
MODIFIERS_FIELD.setInt(field, field.getModifiers() & ~Modifier.FINAL);
} catch (Exception e) {
e.printStackTrace();
return null;
}
try {
return LOOKUP.unreflectSetter(field);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
} }

View File

@ -1,5 +1,5 @@
name: ElementOriginLib name: ElementOriginLib
version: '1.1' version: '1.2'
main: com.io.yutian.elementoriginlib.ElementOriginLib main: com.io.yutian.elementoriginlib.ElementOriginLib
api-version: '1.20' api-version: '1.20'
authors: [ SuperYuTian ] authors: [ SuperYuTian ]