diff --git a/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java b/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java index c3c14b9..d8e5985 100644 --- a/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java @@ -6,6 +6,8 @@ import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import java.io.File; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -19,11 +21,11 @@ public class TDependencyLoader { try { ClassLoader loader = plugin instanceof InternalPlugin ? Bukkit.class.getClassLoader() : plugin.getClass().getClassLoader(); Field ucpField = loader.getClass().getDeclaredField("ucp"); - long ucpOffset = Ref.UNSAFE.objectFieldOffset(ucpField); - Object ucp = Ref.UNSAFE.getObject(loader, ucpOffset); - Method addURL = ucp.getClass().getMethod("addURL", URL.class); - addURL.invoke(ucp, url); - } catch (Exception e) { + long ucpOffset = Ref.getUnsafe().objectFieldOffset(ucpField); + Object ucp = Ref.getUnsafe().getObject(loader, ucpOffset); + MethodHandle methodHandle = Ref.lookup().findVirtual(ucp.getClass(), "addURL", MethodType.methodType(void.class, java.net.URL.class)); + methodHandle.invoke(ucp, url); + } catch (Throwable e) { e.printStackTrace(); } } diff --git a/src/main/scala/io/izzel/taboolib/module/inject/TScheduleLoader.java b/src/main/scala/io/izzel/taboolib/module/inject/TScheduleLoader.java index 09ca9bf..6b17212 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/TScheduleLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/TScheduleLoader.java @@ -65,7 +65,7 @@ public class TScheduleLoader implements TabooLibLoader.Loader { method.invoke(instance); } catch (Throwable t) { try { - method.invoke(Ref.UNSAFE.allocateInstance(pluginClass)); + method.invoke(Ref.getUnsafe().allocateInstance(pluginClass)); } catch (Throwable t2) { t.printStackTrace(); t2.printStackTrace(); diff --git a/src/main/scala/io/izzel/taboolib/util/Ref.java b/src/main/scala/io/izzel/taboolib/util/Ref.java index eec8d1b..9ef6676 100644 --- a/src/main/scala/io/izzel/taboolib/util/Ref.java +++ b/src/main/scala/io/izzel/taboolib/util/Ref.java @@ -12,6 +12,7 @@ import sun.misc.Unsafe; import sun.reflect.Reflection; import javax.annotation.concurrent.ThreadSafe; +import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -19,6 +20,7 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +@SuppressWarnings("restriction") @ThreadSafe public class Ref { @@ -28,16 +30,29 @@ public class Ref { public static final int ACC_BRIDGE = 0x0040; public static final int ACC_SYNTHETIC = 0x1000; - public static final Unsafe UNSAFE = getUnsafe(); + private static final Unsafe UNSAFE; + private static final MethodHandles.Lookup LOOKUP; - static Unsafe getUnsafe() { + static { try { - return (Unsafe) io.izzel.taboolib.util.Reflection.getValue(null, Unsafe.class, true, "theUnsafe"); + UNSAFE = (Unsafe) io.izzel.taboolib.util.Reflection.getValue(null, Unsafe.class, true, "theUnsafe"); + Field lookupField = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP"); + Object lookupBase = UNSAFE.staticFieldBase(lookupField); + long lookupOffset = UNSAFE.staticFieldOffset(lookupField); + LOOKUP = (MethodHandles.Lookup) UNSAFE.getObject(lookupBase, lookupOffset); } catch (Throwable t) { throw new IllegalStateException("Unsafe not found"); } } + public static Unsafe getUnsafe() { + return UNSAFE; + } + + public static MethodHandles.Lookup lookup() { + return LOOKUP; + } + public static List getDeclaredFields(Class clazz) { return getDeclaredFields(clazz, 0, true); } @@ -73,7 +88,7 @@ public class Ref { } catch (Exception | Error e) { try { List list = Arrays.stream(clazz.getDeclaredFields()) - .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); + .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); cachedFields.putIfAbsent(clazz.getName(), list); return list; } catch (Error err) { @@ -117,7 +132,7 @@ public class Ref { } catch (Exception | Error e) { try { List list = Arrays.stream(clazz.getDeclaredMethods()) - .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); + .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); cacheMethods.putIfAbsent(clazz.getName(), list); return list; } catch (Error err) {