Running Julia from JAVA? What is crazier?

I should point out that… From WebIO you can also send/receive JS variables. Also form JavaFX, you can send and receive JS variables as well. So there is another avenue to explore going that way. I don’t want to try it though… it’s too crazy.

So I took the interactive julia REPL to it’s next logical extension and figured I’d share the wealth… I wrote a pretty generic singleton class that lets you write to a REPL and get messages back in Julia. This is kinda nice for an application… While you’re loading your resources kick up a julia instance in another thread and let the precompile whine in the background. No one would ever know :D.

import java.io.*;

class JuliaHook {
    private static JuliaHook single_instance = null;
    private Process juliaServer;
    private BufferedReader stdInput, stdError;
    private BufferedWriter writer;

    private Boolean isAlive(){ return juliaServer.isAlive(); }

    private void REPLIO(){
        stdInput = new BufferedReader(new InputStreamReader(juliaServer.getInputStream()));
        stdError = new BufferedReader(new InputStreamReader(juliaServer.getErrorStream()));
        writer = new BufferedWriter(new OutputStreamWriter(juliaServer.getOutputStream()));
    }

    public void SendToJuliaREPL(String input) throws IOException {
        if( juliaServer.isAlive() ) {
            writer.write(input + "; \n");
            writer.flush();
            stdInput.readLine();
        }
    }

    public String RecieveJuliaREPL() throws IOException {
        if( juliaServer.isAlive() ) {
            String s = null;
            if ((s = stdInput.readLine()) != null) { return s; }
        }
        return "";
    }

    public String SendRecieveJuliaREPL(String input) throws IOException {
        if( juliaServer.isAlive() ) {
            String s = null;
            writer.write(input + "; \n");
            writer.flush();
            if ((s = stdInput.readLine()) != null) { return s; }
        }
        return "";
    }

    private JuliaHook() throws IOException {
        juliaServer = Runtime.getRuntime().exec("julia -i");
        REPLIO();
    }

    public JuliaHook(String absolutepath) throws IOException {
        juliaServer = Runtime.getRuntime().exec("julia -i " + absolutepath);
        REPLIO();
    }

    public static JuliaHook getInstance() throws IOException {
        if (single_instance == null) {
            single_instance = new JuliaHook();
        }
        return single_instance;
    }

    public void killJulia() throws IOException {
        if (single_instance != null) {
            juliaServer.destroy();
            stdInput.close();
            stdError.close();
            writer.flush();
            writer.close();
        }
    }

    public void spawnJuliaREPL() throws IOException {
        if (single_instance != null) {
            juliaServer = Runtime.getRuntime().exec("julia -i ");
            REPLIO();
        }
    }

    public void spawnJuliaREPL(String absolutepath) throws IOException {
        if (single_instance != null) {
            juliaServer = Runtime.getRuntime().exec("julia -i " + absolutepath);
            REPLIO();
        }
    }

    public void spawnJuliaScript(String absolutepath) throws IOException {
        if (single_instance != null) {
            juliaServer = Runtime.getRuntime().exec("julia " + absolutepath);
            REPLIO();
        }
    }
}

3 Likes

Thanks for sharing; I’d also been aiming to set up the Julia connection during launch so, as you note, precompiling (and users) can whine in the background :slight_smile:

1 Like

@lwhitefox I think bundling the project in a docker could really reduce the precompile time if the julia call is done with precompile? Do you have any experience with that?

Interesting thought - I’ve not used docker at all, so I have no insights at all! :woman_shrugging:

I guess the secret sauce there wouldn’t be the docker just the precompile tag… My brain is mush :smiley:

I hate to say it but I think this is a maintenance nightmare. I’m a solo developer, and the amount of nuance associated with java is just not cutting it for me right now. Maybe I have the holiday blues dunno. I think I’m going to go back to investigating pure Julia or some other situation for getting a nice front end - for now anyways. Maybe I’ll have some more ideas, but, I think really all the options I shared are how it can be done.

JNI interface, ZMQ(hooks to an interface API, or use eval dangerously), interactive REPL read and write, or the bizarro open a browser object, and spin up a julia web UI :D. Hope this helps someone else thinking along these lines.

Not at all crazy … would be lovely to be able to implement numerical algorithms in Julia inside a Java application. So, I decided to give this a go to see how well it can be made to work…

Consider it a beta for now. Feedback and contributions most welcome!

Supports standard primitives and arrays only. I don’t have the need for more complex data types, but I’d love to hear from others if there is a strong use case.

4 Likes

have you tried JuliaCaller?

https://github.com/jbytecode/juliacaller

1 Like

Neat! Is this a new project?

1 Like

We can say yes, it’s pretty new, but, it is kinda a replication project of RCaller, the library for interfacing R from within Java.

JuliaCaller creates a Julia process, setups a TCP server in Julia, and starts the server. Julia then accepts connections and performs calculations. JuliaCaller handles the transactions.

RCaller was a little bit different, transactions are handled through streams created on an R process - not any tcp sockets.

RCaller has a larger community and it is used in many projects. JuliaCaller is new as its community is only me (: and not well tested. Hope somebody comes to develop it so we can say it is production ready for the industry :balloon:.

2 Likes

To answer your question I haven’t used JuliaCaller :slight_smile: - yet.

I think you should make a separate thread, maybe a package announcement or a request for comments (RFC) thread. This is a pretty great , project and it would help a lot of people who are stuck in the JVM(java, scala, clojure, groovy, etc). Because writing anything “mathy” on the JVM, in my experience, is horrendous. Meanwhile making little front ends and things in Julia is pretty rough and not so bad in Java.

Are you using ZMQ?

In JuliaCaller, is there a way to pass complex objects from Java to Julia?

In Spark.jl we do a similar thing - when a Julia function is called on elements of RDD (roughly, an iterator with data), on each Spark worker we create a Julia TCP server, connect to it and apply the specified function to RDD. The function to be applied and all the data from JVM is serialized, passed to the Julia server and then the result is sent back to Java side.

This doesn’t work reliably in practice: every now and then people report weird errors coming from serialization, environment inconsistencies, Julia exceptions not properly passed to JVM worker logs, etc. Thus I’m looking for a more reliable options than my own interprocess communication implementation. If JuliaCaller can be used for such a use case, I’d be happy to try it out!

1 Like

Not yet any serialization. But it is possible to convert POJOs to Julia’s structs, Arrays, or Dicts of Any or type String, Any. It is implemented in RCaller. Binary serialization is ofcourse more performant bu it may cause to complications.

1 Like

Thanks, it has a separate thread here.

1 Like

Hi, I am trying to run simple julia script(.jl file) using java. I have used https://github.com/org-arl/jajub to do that. But I am facing issues while initializing JuliaBridge class. Is there any other way to do this. I am new to julia and want to implement this type of interface.
Is there any other way possible, Please help me.

I’ll mention the obvious in the off chance that your Julia code doesn’t need access to the Java data: java.lang.Runtime.exec("julia thescript.jl")

It would help to understand what issues you are facing in using JaJuB to be able to provide concrete guidance.

You need to ensure that julia is in your PATH when running the Java application. Other than that, it should be pretty straightforward for basic operations with primitive or array data types. Have you tried running the example Groovy code (or its equivalent in Java, if you prefer) in the JaJuB README?

I worked myself through the available alternatives to integrate julia into java.
In the end both Jajub and JuliaCaller only worked to some degree. I made some modifications available here: https://github.com/invesdwin/invesdwin-context-julia

Discussions:

  • Jajub: https ://github.com/org-arl/jajub/issues/2
  • JuliaCaller: https ://github.com/jbytecode/juliacaller/issues/1

Both tools did not support multi-line commands, had some compatibility issues and performance bottlenecks.

Other libraries:

  • LibJulia-CLJ (https ://github.com/cnuernber/libjulia-clj) would be very interesting to try, but it seems to be only useable with clojure. Though JNA might provide a faster approach to integrate Julia into Java.
  • Ju4Ja (https ://github.com/lteb2002/ju4ja) seems to be similar to JuliaCaller, though not as developed because the server needs to be setup manually and there is no concept to transport arbitrary data bidirectional.
  • JavaJNI2Julia (https ://github.com/lwhitefox/JavaJNI2Julia) is an example with JNI. Not useable for general purpose scripting.
  • Julia4J (https ://github.com/rssdev10/julia4j) might be another option to JNA with JNI, seems a bit more developed but I could not get the binary to compile on linux, maybe the SWIG files are not up to date to work against newer version of Julia: https ://github.com/rssdev10/julia4j/issues/2

(had to add some spaces to the links because discourse does not allow me to add more than two links)

1 Like

There are now 4 integrations available: Jajub, JuliaCaller, Julia4J, LibJulia-CLJ
Thanks to Julia4j and LibJulia-CLJ authors for helping!

Discussions:

1 Like