javareflectionjarvariadic-functionsbyte-buddy

How to call varargs method in ByteBuddy in a way that bakes the arguments array as constants into the bytecode?


I'm generating classes with ByteBuddy. In one place, I need to call a static utility method which accepts varargs of type String. My code looks like this:

String[] myStringArray = generateParameters()
MethodCall.invoke(utilsCall)
  .with(myStringArray)

This seems to work just fine. While the JVM that generated the code is running, I can create an instance of the generated class via reflection and call the generated method just fine. However, if I call getBytes() on the generated class and write it to a *.jar file, said file will look like this (after decompilation):

public class MyGeneratedClass {

  // $FF: synthetic field
  public static String[] methodCall$p1kp7a1;
  
  public void myGeneratedMethod(){
      MyUtils.myStaticMethod(methodCall$p1kp7a1)
  }

}

Consequently, attempting to load this *.jar file and calling myGeneratedMethod throws a NullPointerException, because the synthetic field generated by ByteBuddy was never initialized. In fact, the generated *.class file does not show any traces of the contents of myStringArray I passed into the method during the initial generation step.

What am I doing wrong? I need to be able to write the generated classes to files and load them in later, with the arguments "baked in".


Solution

  • You are supplying myStringArray directly. Then, Byte Buddy needs to store it. Instead, you would need to supply the argument from a field or a method where it can be supplied. Alternatively, you can add a field manually (via defineField) and initialize it manually such that you do not rely on Byte Buddy's initialization.