2

Let's say I have the following class (or can it be done with an interface also ?) :

class MyCustomClass {
    boolean myCustomMethod(int a, int b){}
}

And the following string :

Math.abs(a - b) >= 10;

Is there a way, with Byte Buddy, to inject the code from the string into a new subclass of MyCustomClass, in the method myCustomMethod ? Even if the String is processed with ANTLR before ?

So I get

class MyCustomClass_SubClassInstance extends MyCustomClass {
    // I know that with ByteBuddy, all this "ceremonial" code is not needed.
    boolean myCustomMethod(int a, int b){
         Math.abs(a - b) >= 10; // Injected code from the string
    }
}
loloof64
  • 5,252
  • 12
  • 41
  • 78

2 Answers2

2

I think you are going down the wrong way. Why use ByteBuddy to generate class code?!

Instead: use the JavaCompiler feature to simply build that class as Java source - then compile it, then use the "dynamically" compiled class.

Meaning: you are somehow overcomplicating things. You actually know what you want to end up with - so create that as java source, and programmatically turn to javac to turn that into byte code.

For Android, the JavaSourceToDex class might be the thing to use.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Thanks, I think I've understood what you mean. My goal is simply to read code from file, and inject it into a subclass anonymous instance (or into an instance of a named subclass) : overall into an android project. So maybe the ByteBuddy library is not suitable for that. Looking at JavaCompiler example. (Edit : seems that the JavaCompiler is the way to go : thank you very much). – loloof64 Jan 25 '18 at 14:36
  • However this method cannot be used for android : there is no class javax.tools.JavaCompiler – loloof64 Jan 25 '18 at 14:42
  • 1
    @loloof64 Not being an android super guru, i still found something that looks promising. See my updated answer. – GhostCat Jan 25 '18 at 16:13
  • Thank you. I'm having a look at it. – loloof64 Jan 25 '18 at 17:28
2

This is not the idea behind Byte Buddy. The Byte Buddy way of doing such a thing would be to implement a class that offers the method you want to invoke and then you generate a proxy to delegate to this method invocation from the instrumented type.

Javassist offers such functionaltiy but performance-wise, it is not great to compile strings at runtime so I would try to avoid this at all costs. Especially on Android where you typically have limited ressources. Class generation is quite expensive.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • Thank you for this clarification. Meanwhile generating code from String is an important feature that I need, and I will try with DexMaker, as Kotlin does not support metaprogramming and I need a way for users to make their own function (or lambda) from a file. Because what I try to achieve is impossible otherwise. Anyway thank you for pointing me this limitation :) – loloof64 Jan 26 '18 at 10:53
  • Finally, I'll follow your advice of not compiling strings at runtime with a bytecode manipulator, as I found a better way to fill my needs : thanks to ANTLR4 and a custom class hierarchy and evaluator function. Thank again for pointing me that my idea was way too bad for Android system, making me reconsider my strategy. – loloof64 Jan 26 '18 at 12:17