Skip to content

Commit

Permalink
Here's a small function that allows you to initialize JavaCall from i…
Browse files Browse the repository at this point in the history
…nside Java (#90)

* allow initializing from running VM to allow call-in/call-out

created init_current_vm function

* untabified example code

* Added usage section to doc/index.md

* slight wording improvement
  • Loading branch information
zot authored and aviks committed Sep 10, 2018
1 parent 7d1d62c commit d6c3678
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 0 deletions.
38 changes: 38 additions & 0 deletions doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,44 @@ julia> jcall(j_u_arrays, "binarySearch", jint, (Array{jint,1}, jint), [10,20,30,
```

##Usage from a running JVM

Use JNI or JNA to initialize a Julia VM, then call `JavaCall.init_current_vm()`. Here's an example using JNA:

```java
package zot.julia;

import com.sun.jna.Native;

public class Julia {
static {
Native.register("julia");
jl_init__threading();
}

public static double bubba = Math.random();

public static native void jl_init__threading();
public static native void jl_eval_string(String code);
public static native void jl_atexit_hook(int status);

public static void main(String args[]) {
System.out.println("test");
jl_eval_string("println(\"test from Julia\")");
jl_eval_string("using JavaCall");
jl_eval_string("JavaCall.init_current_vm()");
jl_eval_string("println(\"initialized VM\")");
jl_eval_string("jlm = @jimport java.lang.Math");
jl_eval_string("println(jcall(jlm, \"sin\", jdouble, (jdouble,), pi/2))");
jl_eval_string("jl = @jimport zot.julia.Julia");
System.out.println("Bubba should be " + bubba);
jl_eval_string("println(\"bubba: \", jfield(jl, \"bubba\", jdouble))");
jl_eval_string("println(\"Done with tests\")");
jl_atexit_hook(0);
}
}
```

##Major TODOs and Caveats

* Currently, only a low level interface is available, via `jcall`. As a result, this package is best suited for writing libraries that wrap around existing java packages. Writing user code direcly using this interface might be a bit tedious at present. A high level interface using reflection will eventually be built.
Expand Down
55 changes: 55 additions & 0 deletions src/jvm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,61 @@ function init(opts)
return
end

"""
init_current_vm()
Allow initialization from running VM. Uses the first VM it finds.
# Example using JNA
```java
package zot.julia;
import com.sun.jna.Native;
public class Julia {
static {
Native.register("julia");
jl_init__threading();
}
public static double bubba = Math.random();
public static native void jl_init__threading();
public static native void jl_eval_string(String code);
public static native void jl_atexit_hook(int status);
public static void main(String args[]) {
System.out.println("test");
jl_eval_string("println(\"test from Julia\")");
jl_eval_string("using JavaCall");
jl_eval_string("JavaCall.init_current_vm()");
jl_eval_string("println(\"initialized VM\")");
jl_eval_string("jlm = @jimport java.lang.Math");
jl_eval_string("println(jcall(jlm, \"sin\", jdouble, (jdouble,), pi/2))");
jl_eval_string("jl = @jimport zot.julia.Julia");
System.out.println("Bubba should be " + bubba);
jl_eval_string("println(\"bubba: \", jfield(jl, \"bubba\", jdouble))");
jl_eval_string("println(\"Done with tests\")");
jl_atexit_hook(0);
}
}
```
"""
function init_current_vm()
ppjvm = Array{Ptr{JavaVM}}(undef, 1)
ppenv = Array{Ptr{JNIEnv}}(undef, 1)
pnum = Array{Cint}(undef, 1)
ccall(Libdl.dlsym(libjvm, :JNI_GetCreatedJavaVMs), Cint, (Ptr{Ptr{JavaVM}}, Cint, Ptr{Cint}), ppjvm, 1, pnum)
global pjvm = ppjvm[1]
jvm = unsafe_load(pjvm)
global jvmfunc = unsafe_load(jvm.JNIInvokeInterface_)
ccall(jvmfunc.GetEnv, Cint, (Ptr{Nothing}, Ptr{Ptr{JNIEnv}}, Cint), pjvm, ppenv, JNI_VERSION_1_8)
global penv = ppenv[1]
jnienv = unsafe_load(penv)
global jnifunc = unsafe_load(jnienv.JNINativeInterface_) #The JNI Function table
end

function destroy()
if (!isdefined(JavaCall, :penv) || penv == C_NULL)
throw(JavaCallError("Called destroy without initialising Java VM"))
Expand Down

0 comments on commit d6c3678

Please sign in to comment.