Slide 1

Slide 1 text

How to generate JAR file dynamically compiling Java code in Kotlin Mitsunori Komatsu

Slide 2

Slide 2 text

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)

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Where can we see the source code? https://github.com/komamitsu/tiny- kotlin-lisp

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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…

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Create a JAR file from the byte code and dependent classes @CompileVisitor.kt Setup a manifest Create a JAR file reading class files

Slide 13

Slide 13 text

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.

Slide 14

Slide 14 text

Enjoy programming!