Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to generate JAR file dynamically compiling ...

How to generate JAR file dynamically compiling Java code in Kotlin

Mitsunori Komatsu

February 26, 2023
Tweet

More Decks by Mitsunori Komatsu

Other Decks in Technology

Transcript

  1. About me • Mitsunori Komatsu, 
 Software engineer at Treasure

    Data • github:komamitsu
 msgpack-java
 (jackson-dataformat-msgpack),
 fluency (yet another fluent logger java)
 treasuredata_fdw (with td-client-rust)
  2. Why did I try it? • First, I developed just

    a tiny Lisp interpreter in Kotlin for exercise • But basically, interpreters aren’t so fast. So, I tried dynamically compiling Lisp code to Java byte code • Finally, I tried outputting those Java byte code to a JAR file
  3. How did I do that? • Convert Lisp AST to

    Java source code traversing the tree using Visitor pattern • Compile the Java source code using http://janino-compiler.github.io/janino/ • Extract the Java byte code with a bit hack • Create a JAR file from the byte code and dependent classes
  4. Convert Lisp AST to Java source code traversing the tree

    using Visitor pattern @CompileVisitor.kt Nothing special…
  5. Convert Lisp AST to Java source code traversing the tree

    using Visitor pattern @CompileVisitor.kt Nothing special…
  6. http://janino-compiler.github.io/janino/ With Janino!! Janino can not only compile a set

    of source files to a set of class files like JAVAC, but also compile a Java expression, block, class body or source file in memory, load the bytecode and execute it directly in the same JVM. Compile the Java source code
  7. Compile the Java source code and Extract the Java byte

    code • It’s really easy to dynamically compile Java source code and invoke it with Janino • But Janino doesn’t provide any API to get compiled Java byte code…
  8. Compile the Java source code and Extract the Java byte

    code Compile Extract Access a hidden field ByteArrayClassLoader.classes in Janino using reflection! @CompileVisitor.kt
  9. Create a JAR file from the byte code and dependent

    classes Prepare dependent class files @CompileVisitor.kt Create the compiled class file Get Java byte code using Class#getResourceAsStream
  10. Create a JAR file from the byte code and dependent

    classes @CompileVisitor.kt Setup a manifest Create a JAR file reading class files
  11. Pitfalls @CompileVisitor.kt • When writing Kotlin code, it easily has

    dependencies with internal Kotlin classes (e.g kotlin.KotlinNullPointerException). So the classes are needed to be included in a JAR file to avoid runtime failures.