Is it easier to embed Julia into the Java Virtual Machine (JVM) or easier to embed the JVM into Julia?
Embedding the JVM into Julia
I’ve been working with @avik on JavaCall.jl for the better part of this year. To make JavaCall work, there have been several hoops to jump through, notably the JULIA_COPY_STACKS
environmental variable that modifies Julia’s Task
implementation. On Linux, I’ve found setting JULIA_COPY_STACKS=1
works quite smoothly. However, this need is also inconsistent on the Windows operating system, which doesn’t appear to need JULIA_COPY_STACKS=1
for single threaded operation. The main difficulty is the JVM’s dependence on using signal handling for basic operations. How Julia’s Task
s interact with Java signal handling due to stack semantics creates an undesirable situation. The JVM is a bit challenging to embed, and Julia’s Task
semantics make it even trickier.
Embedding Julia into the JVM
Embedding Julia in Java has been tried a number of times with varying success. For example, @jbytecode’s JuliaCaller connects Julia via TCP, which is great clean solution, but sharing memory becomes difficult:
@rssdev10’s Julia4J uses SWIG to build a Java Native Interface (JNI) integration with Julia which promises efficiency, but this requires a compiler on the user end for a specific JVM:
@cnuernber recently has built Java Native Access bindings from Clojure (a LISP dialect that runs on JVM) to Julia, meaning that libjulia can now be dynamically linked into the JVM. No compiler needed.
Using Julia from the JVM (Clojure)
While there were some early hiccups, it turns out that Julia has enough options to allow it to play nice with others as we found in Consistent crash attempting to embed Julia in Java via dynamically loading libjulia.so · Issue #36092 · JuliaLang/julia · GitHub . They key in this instance was turning off Julia’s signal handling:
jl_options.handle_signals = JL_OPTIONS_HANDLE_SIGNALS_OFF
Based upon libjulia-clj’s cross platform success based on Travis tests, this path is looking quite promising.
Once linked together, Julia should then be able to leverage JavaCall to call back into the JVM. JavaCall, for example, has an alternate initialization routine in JavaCall.JNI.init_current_vm
I don’t mean to disparage the prior methods. Each has it’s own advantages and disadvantages. Network based integration via TCP should be quite robust and scalable. Java Native Interface comes with a low overhead. The Java Native Access approach is user friendly middle ground.
Overall, the approach of embedding Julia into the Java Virtual Machine using Java Native Access looks quite promising. This bodes well for future cooperation between Julia, Java, and other JVM-based languages like Clojure, Scala, and Kotlin. Embedding Julia into the JVM appears to be the easier path forward.