How to generate JAR file dynamically compiling Java code in Kotlin
1. How to generate JAR file dynamically
compiling Java code in Kotlin
Mitsunori Komatsu
2. 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)
3. 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
4. Where can we see the
source code?
https://github.com/komamitsu/tiny-
kotlin-lisp
5. 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
6. Convert Lisp AST to Java source code
traversing the tree using Visitor pattern
@CompileVisitor.kt
Nothing special…
7. Convert Lisp AST to Java source code
traversing the tree using Visitor pattern
@CompileVisitor.kt
Nothing special…
8. 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
9. 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…
10. 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
11. 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
12. Create a JAR file from the byte
code and dependent classes
@CompileVisitor.kt
Setup a manifest
Create a JAR file reading class files
13. 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.