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

Allow customization of MethodType used for invokedynamic-advices #1749

Open
JonasKunz opened this issue Jan 13, 2025 · 1 comment
Open

Allow customization of MethodType used for invokedynamic-advices #1749

JonasKunz opened this issue Jan 13, 2025 · 1 comment
Assignees
Milestone

Comments

@JonasKunz
Copy link

Example Advice:

class MyAdvice {
 @Advice.OnMethodEnter(suppress = Throwable.class, inline = false)
  public static LocalHelper onMethodEnter() {
    return new LocalHelper();
  }

  @Advice.AssignReturned.ToReturned
  @Advice.OnMethodExit(
      suppress = Throwable.class,
      onThrowable = Throwable.class,
      inline = false)
  public static LocalHelper onMethodExit(@Advice.Enter LocalHelper enterVal) {
    return enterVal;
  }
}

When weaving this instrumentation into the target using invokedynamic, currently a MethodType with the exact type of the @OnMethodEnter / @OnMethodExit types is generated. However, with invokedynamic the Advice might live in a very different classloader with different types visible to it.

E.g. in the example, LocalHelper might not be visible to the instrumented class, but only to the classloader loading the advice.
This is nicely supported by the JVM: We can just replace LocalHelper with Object and in the MethodType used for the invokedynamic-instruction and adapt the MethodHandle at bootstrap time using MethodHandle.asType.

This is however currently not supported by bytebuddy: The MethodType used is always the exact type of the target advice method. We'd like to be able to:

  • Customize the MethodType of the invokedynamic instruction inserted (e.g. erasing types)
  • Still preserve the original MethodType as a literal string to be passed to the invokedynamic-bootstrapping, so that we can lookup the correct target MethodHandle before adapting it with MethodHandle.asType

An ugly workaround currently available is implemented here. There we perform the type-erasure on the advice via ASM before it is analyzed by bytebuddy. We preserve the original signature as a string in an annotation value and pass it to the bootstrapping method as a constant argument.

@raphw raphw self-assigned this Jan 14, 2025
@raphw raphw added the question label Jan 14, 2025
@raphw raphw added this to the 1.15.11 milestone Jan 14, 2025
@raphw
Copy link
Owner

raphw commented Jan 14, 2025

Alright, I even had a branch ready which I now polished and merged to master. You can now supply a visitor to the bootstrap method which transforms the types that are passed to avoid. As today, you can then implement a bootstrap method resolver that supplies suitable arguments to pass to the boot method.

There's also a new default visitor (Generalizing) which reduces all reference types to Object.

Does that work for the demand in question? I wanted to wait for your feedback before releasing the API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants