如何使用混入(Mixin)向lambda表达式注入内容?
我正在制作一个Minecraft模组,需要添加一个Mixin,目标是在lambda体内的方法调用上。
我有如下目标类:
public class Foo {
public static void bar() {
Thread thread = new Thread(() -> {
System.out.println("Hello World!");
//Inject Here!
});
}
}
以及我有的Mixin类
@Mixin(Foo.class)
public abstract class FooMixin {
@Inject(
method = "lambda$bar$0()V",
at = @At(
value = "INVOKE",
target = "Ljava/io/PrintStream;println(Ljava/lang/String)"
shift = At.Shift.AFTER
))
public void doSomething(CallbackInfo ci) {
System.out.println("The mixin has succeeded")
}
}
at 和 method 参数应该怎么写?
我知道lambda表达式在字节码中以名为 lambda$method$X 的方法存储,但当我把它用于 method 参数时,Mixin找不到该方法并抛出错误。
下面是堆栈跟踪:
[15:41:21] [Render thread/ERROR] (FabricLoader/Mixin) Mixin apply for mod pictureperfect failed pictureperfect.mixins.json:FooMixin from mod pictureperfect -> com.itsnukea.pictureperfect.Foo: org.spongepowered.asm.mixin.injection.throwables.InvalidInjectionException Error whilst instancing injection point org.spongepowered.asm.mixin.injection.points.BeforeInvoke for INVOKE [INJECT_PREPARE Applicator Phase -> pictureperfect.mixins.json:FooMixin from mod pictureperfect -> Prepare Injections -> handler$zdc000$pictureperfect$doSomething(Lorg/spongepowered/asm/mixin/injection/callback/CallbackInfo;)V -> Parse -> -> Parse Injection Points]
org.spongepowered.asm.mixin.injection.throwables.InvalidInjectionException: Error whilst instancing injection point org.spongepowered.asm.mixin.injection.points.BeforeInvoke for INVOKE [INJECT_PREPARE Applicator Phase -> pictureperfect.mixins.json:FooMixin from mod pictureperfect -> Prepare Injections -> handler$zdc000$pictureperfect$doSomething(Lorg/spongepowered/asm/mixin/injection/callback/CallbackInfo;)V -> Parse -> -> Parse Injection Points]
at org.spongepowered.asm.mixin.injection.InjectionPoint.create(InjectionPoint.java:876) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.injection.InjectionPoint.parse(InjectionPoint.java:840) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.injection.InjectionPoint.parse(InjectionPoint.java:788) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.injection.InjectionPoint.parse(InjectionPoint.java:708) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.injection.struct.InjectionInfo.parseInjectionPoints(InjectionInfo.java:439) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.injection.struct.InjectionInfo.readAnnotation(InjectionInfo.java:371) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.injection.struct.InjectionInfo.<init>(InjectionInfo.java:340) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.injection.struct.InjectionInfo.<init>(InjectionInfo.java:331) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.injection.struct.CallbackInjectionInfo.<init>(CallbackInjectionInfo.java:48) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62) ~[?:?]
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502) ~[?:?]
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486) ~[?:?]
at org.spongepowered.asm.mixin.injection.struct.InjectionInfo$InjectorEntry.create(InjectionInfo.java:196) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.injection.struct.InjectionInfo.parse(InjectionInfo.java:664) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.transformer.MixinTargetContext.prepareInjections(MixinTargetContext.java:1396) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.transformer.MixinApplicatorStandard.prepareInjections(MixinApplicatorStandard.java:731) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.transformer.MixinApplicatorStandard.applyMixin(MixinApplicatorStandard.java:315) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.transformer.MixinApplicatorStandard.apply(MixinApplicatorStandard.java:246) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.transformer.TargetClassContext.apply(TargetClassContext.java:437) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.transformer.TargetClassContext.applyMixins(TargetClassContext.java:418) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.transformer.MixinProcessor.applyMixins(MixinProcessor.java:352) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.transformer.MixinTransformer.transformClass(MixinTransformer.java:237) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at org.spongepowered.asm.mixin.transformer.MixinTransformer.transformClassBytes(MixinTransformer.java:202) ~[sponge-mixin-0.17.0+mixin.0.8.7.jar:0.17.0+mixin.0.8.7]
at net.fabricmc.loader.impl.launch.knot.KnotClassDelegate.getPostMixinClassByteArray(KnotClassDelegate.java:435) ~[fabric-loader-0.18.4.jar:?]
at net.fabricmc.loader.impl.launch.knot.KnotClassDelegate.tryLoadClass(KnotClassDelegate.java:336) ~[fabric-loader-0.18.4.jar:?]
at net.fabricmc.loader.impl.launch.knot.KnotClassDelegate.loadClass(KnotClassDelegate.java:231) ~[fabric-loader-0.18.4.jar:?]
at net.fabricmc.loader.impl.launch.knot.KnotClassLoader.loadClass(KnotClassLoader.java:119) ~[fabric-loader-0.18.4.jar:?]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) ~[?:?]
at knot/com.itsnukea.pictureperfect.PicturePerfect.onInitializeClient(PicturePerfect.java:24) ~[main/:?]
at net.fabricmc.loader.impl.FabricLoaderImpl.invokeEntrypoints(FabricLoaderImpl.java:405) [fabric-loader-0.18.4.jar:?]
at net.fabricmc.loader.impl.game.minecraft.Hooks.startClient(Hooks.java:53) [fabric-loader-0.18.4.jar:?]
at knot/net.minecraft.client.MinecraftClient.<init>(MinecraftClient.java:483) [minecraft-merged-82357b8541-1.21.10-net.fabricmc.yarn.1_21_10.1.21.10+build.2-v2.jar:?]
at knot/net.minecraft.client.main.Main.main(Main.java:234) [minecraft-merged-82357b8541-1.21.10-net.fabricmc.yarn.1_21_10.1.21.10+build.2-v2.jar:?]
at net.fabricmc.loader.impl.game.minecraft.MinecraftGameProvider.launch(MinecraftGameProvider.java:514) [fabric-loader-0.18.4.jar:?]
at net.fabricmc.loader.impl.launch.knot.Knot.launch(Knot.java:72) [fabric-loader-0.18.4.jar:?]
at net.fabricmc.loader.impl.launch.knot.KnotClient.main(KnotClient.java:23) [fabric-loader-0.18.4.jar:?]
at net.fabricmc.devlaunchinjector.Main.main(Main.java:86) [dev-launch-injector-0.2.1+build.8.jar:?]
我不能 @Redirect 或 @ModifyArg 该lambda,因为这很可能会与其他模组产生兼容性问题
解决方案
你已经非常接近了,只需要修正描述符。
Correct version:
@Mixin(Foo.class)
public abstract class FooMixin {
@Inject(
method = "lambda$bar$0()V",
at = @At(
value = "INVOKE",
target = "Ljava/io/PrintStream;println(Ljava/lang/String;)V",
shift = At.Shift.AFTER,
remap = false
)
)
private static void doSomething(CallbackInfo ci) {
System.out.println("The mixin has succeeded");
}
}
Key fixes:
method = "lambda$bar$0()V"(不是"(;)V")target必须包含返回类型 ->...;)V- 为JDK方法添加
remap = false - 让injector
static(lambda是静态的)
就这些。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。