如何使用混入(Mixin)向lambda表达式注入内容?

编程语言 2026-07-11

我正在制作一个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")
    }
}

atmethod 参数应该怎么写?

我知道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:

  1. method = "lambda$bar$0()V"(不是 "(;)V"
  2. target 必须包含返回类型 -> ...;)V
  3. 为JDK方法添加 remap = false
  4. 让injector static(lambda是静态的)

就这些。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章