diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java index fadd54ebc9..3cbcc57385 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java @@ -38,6 +38,11 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import java.io.IOException; +import java.lang.invoke.CallSite; +import java.lang.invoke.LambdaMetafactory; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; @@ -57,8 +62,6 @@ import javax.inject.Singleton; import javax.swing.SwingUtilities; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import net.runelite.client.events.SessionClose; -import net.runelite.client.events.SessionOpen; import net.runelite.client.RuneLite; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigManager; @@ -66,11 +69,14 @@ import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.PluginChanged; +import net.runelite.client.events.SessionClose; +import net.runelite.client.events.SessionOpen; import net.runelite.client.task.Schedule; import net.runelite.client.task.ScheduledMethod; import net.runelite.client.task.Scheduler; import net.runelite.client.ui.SplashScreen; import net.runelite.client.util.GameEventManager; +import net.runelite.client.util.ReflectUtil; @Singleton @Slf4j @@ -501,7 +507,30 @@ public class PluginManager continue; } - ScheduledMethod scheduledMethod = new ScheduledMethod(schedule, method, plugin); + Runnable runnable = null; + try + { + final Class clazz = method.getDeclaringClass(); + final MethodHandles.Lookup caller = ReflectUtil.privateLookupIn(clazz); + final MethodType subscription = MethodType.methodType(method.getReturnType(), method.getParameterTypes()); + final MethodHandle target = caller.findVirtual(clazz, method.getName(), subscription); + final CallSite site = LambdaMetafactory.metafactory( + caller, + "run", + MethodType.methodType(Runnable.class, clazz), + subscription, + target, + subscription); + + final MethodHandle factory = site.getTarget(); + runnable = (Runnable) factory.bindTo(plugin).invokeExact(); + } + catch (Throwable e) + { + log.warn("Unable to create lambda for method {}", method, e); + } + + ScheduledMethod scheduledMethod = new ScheduledMethod(schedule, method, plugin, runnable); log.debug("Scheduled task {}", scheduledMethod); scheduler.addScheduledMethod(scheduledMethod); diff --git a/runelite-client/src/main/java/net/runelite/client/task/ScheduledMethod.java b/runelite-client/src/main/java/net/runelite/client/task/ScheduledMethod.java index e91a5a89ff..5e39b49f0e 100644 --- a/runelite-client/src/main/java/net/runelite/client/task/ScheduledMethod.java +++ b/runelite-client/src/main/java/net/runelite/client/task/ScheduledMethod.java @@ -26,49 +26,22 @@ package net.runelite.client.task; import java.lang.reflect.Method; import java.time.Instant; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.ToString; +@RequiredArgsConstructor +@ToString +@Getter public class ScheduledMethod { private final Schedule schedule; private final Method method; private final Object object; + @EqualsAndHashCode.Exclude + private final Runnable lambda; + @Setter private Instant last = Instant.now(); - - public ScheduledMethod(Schedule schedule, Method method, Object object) - { - this.schedule = schedule; - this.method = method; - this.object = object; - } - - @Override - public String toString() - { - return "ScheduledMethod{" + "schedule=" + schedule + ", method=" + method + ", object=" + object + '}'; - } - - public Schedule getSchedule() - { - return schedule; - } - - public Method getMethod() - { - return method; - } - - public Object getObject() - { - return object; - } - - public Instant getLast() - { - return last; - } - - public void setLast(Instant last) - { - this.last = last; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/task/Scheduler.java b/runelite-client/src/main/java/net/runelite/client/task/Scheduler.java index 2f6446c3ab..8ecf6ab665 100644 --- a/runelite-client/src/main/java/net/runelite/client/task/Scheduler.java +++ b/runelite-client/src/main/java/net/runelite/client/task/Scheduler.java @@ -93,11 +93,18 @@ public class Scheduler private void run(ScheduledMethod scheduledMethod) { - Method method = scheduledMethod.getMethod(); - try { - method.invoke(scheduledMethod.getObject()); + Runnable lambda = scheduledMethod.getLambda(); + if (lambda != null) + { + lambda.run(); + } + else + { + Method method = scheduledMethod.getMethod(); + method.invoke(scheduledMethod.getObject()); + } } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {