From 9b37d2a330fd2aa030057aca86ca717588c8307e Mon Sep 17 00:00:00 2001 From: YuTian <2953516620@qq.com> Date: Thu, 8 Aug 2024 01:15:40 +0800 Subject: [PATCH] 1.2 --- .../elementoriginlib/util/ReflectionUtil.java | 137 ++++++++++++++++++ src/main/resources/plugin.yml | 2 +- 2 files changed, 138 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/io/yutian/elementoriginlib/util/ReflectionUtil.java b/src/main/java/com/io/yutian/elementoriginlib/util/ReflectionUtil.java index 4dca45a..3f689db 100644 --- a/src/main/java/com/io/yutian/elementoriginlib/util/ReflectionUtil.java +++ b/src/main/java/com/io/yutian/elementoriginlib/util/ReflectionUtil.java @@ -3,7 +3,10 @@ package com.io.yutian.elementoriginlib.util; import org.bukkit.Bukkit; import sun.misc.Unsafe; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.security.AccessController; 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; + } + } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index e7c1ade..76e68cd 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: ElementOriginLib -version: '1.1' +version: '1.2' main: com.io.yutian.elementoriginlib.ElementOriginLib api-version: '1.20' authors: [ SuperYuTian ]