Xavier Coulon
Xavier Coulon

Reputation: 1600

Changing the visibility of a method

Is it possible to (just) change the visibility of some methods with Byte Buddy ? I have a user class with private static methods, and I'd need to delegate some calls to those methods, but it currently fails because they are private. So, I wonder if I can redefine the user class, by tranforming the aforementioned methods by adding a public modifier.

For the record, calling setAccessible(true) method on the target Java method as not effect, as Byte Buddy still fails with the following exception:

java.lang.IllegalStateException: class net.bytebuddy.renamed.java.lang.Object$ByteBuddy$VHdvjIkb cannot see private java.lang.String org.mockaccino.MockaccinoTest.lambda$3() throws java.lang.Exception
at net.bytebuddy.implementation.MethodCall$MethodInvoker$ForContextualInvocation.invoke(MethodCall.java:2387)
...

I've found some APIs that might do the trick, but I need to instrument the methods, which is not needed in my case.

Eg:

byteBuddy.redefine(targetClass)
  .method(ElementMatchers.named(targetMethod.getName()))
  .intercept(???)
  .transform(Transformer.ForMethod.withModifiers(Visibility.PUBLIC))
  .make()
  .load(getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());

My question is: is there an interceptor that is able of calling the body of source method that is being redefined ?

Or is there another way to make the target methods publicly visible ?

Upvotes: 1

Views: 1370

Answers (1)

Rafael Winterhalter
Rafael Winterhalter

Reputation: 43972

Redefining a method's modifiers would not work with a loaded class. The JVM rejects any redefinitions that add/remove a method or that change any method's properties, e.g. its modifiers.

In order to make methods public, you would need to apply a rebasement rather then a redefinition where you instrument the methods by SuperMethodCall.INSTANCE. This transformation would need to be applied before the first loading of the class in question.

Upvotes: 2

Related Questions