Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advice method contains asynchronization code will throw IllegalAccessError #1614

Open
MrLiuzy opened this issue Apr 9, 2024 · 1 comment
Assignees
Labels
Milestone

Comments

@MrLiuzy
Copy link

MrLiuzy commented Apr 9, 2024

version 1.12.19
recurrence this issue by running code below :

import java.util.Arrays;
import java.util.concurrent.CompletableFuture;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
import net.bytebuddy.matcher.ElementMatchers;

public class ByteBuddyAdviceTest {

    public static class Target {
        public void sayHello(String hello) {
            System.out.println(hello);
        }
    }
    
    public static class TargetAgent {
        
        @Advice.OnMethodExit
        public static void methodExit(@Advice.AllArguments Object[] args) {
            System.err.println("方法退出, 参数:" + Arrays.toString(args));
            // success
            otherMethod(args);
            // Exception in thread "main" java.lang.BootstrapMethodError: java.lang.IllegalAccessError: tried to access method ...
            CompletableFuture.runAsync(()->{});
        }
        
        static void otherMethod(Object[] args) {
            CompletableFuture.runAsync(() -> System.out.println("otherMethod"));
        }
    }
    
    public static void main(String[] args) {
        ByteBuddyAgent.install();
        // @formatter:off
        new ByteBuddy()
            .redefine(Target.class)
            .visit(Advice.to(TargetAgent.class).on(ElementMatchers.named("sayHello")))
            .make()
            .load(Target.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent())
            ;
        // @formatter:on
        new Target().sayHello("hello byte buddy");
    }
}
@raphw
Copy link
Owner

raphw commented Apr 9, 2024

This is because of the lambda expression. It's compiled to a method of its own which is not visible after inlining.

You should avoid lambdas and rather create explicit classes that you need to inject into the targeted class loader using ClassInjector. Then thereafter you can instantiate the callback explicitly and provide it where you now place the lambda.

@raphw raphw self-assigned this Apr 9, 2024
@raphw raphw added the question label Apr 9, 2024
@raphw raphw added this to the 1.14.13 milestone Apr 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants