Git Product home page Git Product logo

javacall.jl's People

Contributors

abhijithch avatar abread avatar adambrewster avatar ahnlabb avatar andygreenwell avatar asinghvi17 avatar aviks avatar dfdx avatar dourouc05 avatar expandingman avatar femtocleaner[bot] avatar github-actions[bot] avatar juliatagbot avatar marcono1234 avatar matfi avatar mbeltagy avatar mdpradeep avatar mkitti avatar non-jedi avatar pallharaldsson avatar rainerheintzmann avatar satanja avatar scottpjones avatar simonbyrne avatar staticfloat avatar sylvaticus avatar tanmaykm avatar tkelman avatar wateim avatar zot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

javacall.jl's Issues

Should JavaCall be using global refs instead of local ones?

The JNI docs say that local refs are only valid for the duration of a JNI call, yet it looks to me as if JavaObject holds onto its local ref until Julia garbage collects the JavaObject.

This seems like it would create unstable references. In fact I have seen JavaObjects that appear to change class spontaneously and I am wondering if there is a connection.

Should JavaCall be changed to use global refs instead of local ones?

Test with Java 9? And not 7?

I see "It has also been shown to work with OpenJDK flavour of java, versions 7 and 8."

I'm not up-to-speed on all Java 9 changes, I assume it just works, and just needs testing to confirm. Is there anything extra that needs actual programming, to work with?

I see elsewhere support Java 7 and 8 not 6 and 7, so maybe you don't want to drop statement on Java 7..

dfdx/Spark.jl@d3674e0

“No Java runtime present, requesting install.” message on MacOS Catalina

On MacOS Catalina I'm seeing the dialog “No Java runtime present, requesting install.” in JavaCall.jl when my Java code executes .getDeclaredConstructor().newInstance(). Julia terminates at this point. I tried with Julia 1.3.0 and 1.3.1. The code does work correctly in our non-Julia application. Also all tests in ]test JavaCall pass.

I've tried several JDK versions, all producing the dialog.

It's not possible to install the legacy Java 6 runtime anymore.

This used to work and I don't understand what update is causing the dialog.

Does anybody have an idea how to solve this?

               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.3.0 (2019-11-26)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

(v1.3) pkg> status JavaCall
    Status `~/.julia/environments/v1.3/Project.toml`
  [864edb3b] DataStructures v0.17.7
  [494afd89] JavaCall v0.7.2
  [ade2ca70] Dates 

⋊> ~/D/W/S/E/2020-jan-03 java --version                                                                                                                                                                                                         16:50:48
openjdk 11.0.1 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)

Tag for 0.5

JuliaDatabases/JDBC.jl#20 says it's needed.

I'm not sure if 0.5 is already done with:
66af85a

as I see tests failing. Is that a false alarm since there is no tag? I'm just new to this, and can't see the test [that are failing]..

crash

I can run a query 4 times correctly but the 5th time it crashes when doing ResultSet.getString("field")

in Java 7 this gives a NullPointerException
in Java 8 (after disabling the assertion for JNI version 1.6 to be able to run it) it crashes julia itself with a segmentation fault:

julia testRandom.jl
Found libjvm @ /usr/lib/jvm/java-8-oracle/jre/lib/amd64/server
loading data

signal (11): Segmentation fault
jl_f_get_field at /usr/bin/../lib/x86_64-linux-gnu/julia/libjulia.so (unknown line)
geterror at /home/steven/.julia/v0.3/JavaCall/src/JavaCall.jl:209
_jcall at /home/steven/.julia/v0.3/JavaCall/src/JavaCall.jl:276
jl_apply_generic at /usr/bin/../lib/x86_64-linux-gnu/julia/libjulia.so (unknown line)
jl_f_apply at /usr/bin/../lib/x86_64-linux-gnu/julia/libjulia.so (unknown line)
jcall at /home/steven/.julia/v0.3/JavaCall/src/JavaCall.jl:236
jl_apply_generic at /usr/bin/../lib/x86_64-linux-gnu/julia/libjulia.so (unknown line)
loadData at /media/sf_Documents/julia_workspace/VMRecommender/src/VMRecommender.jl:194

Segfault in tests?

This looks like a segfault in the tests. Is this expected?

julia> Pkg.test("JavaCall")
INFO: Testing JavaCall
Loaded /Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/lib/server/libjvm.dylib
Julia Version 0.5.0-pre+5697
Commit 3d80eae* (2016-07-26 08:48 UTC)
Platform Info:
  System: Darwin (x86_64-apple-darwin15.4.0)
  CPU: Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.7.1 (ORCJIT, broadwell)

signal (11): Segmentation fault: 11
while loading /Users/ranjan/.julia/v0.5/JavaCall/test/runtests.jl, in expression starting on line 9
unknown function (ip: 0x319bce2b3)
Allocations: 2769286 (Pool: 2768126; Big: 1160); GC: 2
In Java, recd: 10
In Java, recd: 10
In Java, recd: 10
In Java, recd: 2147483647
In Java, recd: 9223372036854775807

.
.
.

JClass is not properly supported

Although in Java Class is, well, a class itself, in JavaCall it is not an instance of JavaObject. This leads to errors in some cases. Here's an example.

First, let's call .toString() method of some object to make sure we do everything right:

julia> using JavaCall
Loaded /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server/libjvm.so

julia> JavaCall.init([])

julia> jcall(JString("test"), "toString", JString, ())
"test"

And now let's do the same thing with .getClass which returns JClass:

julia> jcall(JString("test"), "getClass", JClass, ())
ERROR: `write` has no method matching write(::IOBuffer, ::Nothing)
 in write at io.jl:32
 in method_signature at /home/<username>/.julia/v0.3/JavaCall/src/JavaCall.jl:447
 in jcall at /home/<username>/.julia/v0.3/JavaCall/src/JavaCall.jl:271

The error comes from signature() method which is supposed to return single-character descriptor of a type, but, when given JClass, returns nothing:

julia> JavaCall.signature(JString)
"Ljava/lang/String;"

julia> JavaCall.signature(JClass)

julia>

Most probably, for this specific case it's possible to simply overload signature() method, but I'm not sure there will be no other issues with distinction between JClass / JavaObject, so I leave this design question to you.

can't `init()` on OS X

this is on master with julia 0.6:

julia> using JavaCall

WARNING: deprecated syntax "inner constructor JavaObject(...) around /Users/arthurb/.julia/v0.6/JavaCall/src/core.jl:30".
Use "JavaObject{T}(...) where T" instead.

WARNING: deprecated syntax "inner constructor JavaObject(...) around /Users/arthurb/.julia/v0.6/JavaCall/src/core.jl:35".
Use "JavaObject{T}(...) where T" instead.
Loaded /Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/jre/lib/server/libjvm.dylib

julia> JavaCall.init()

signal (11): Segmentation fault: 11
while loading no file, in expression starting on line 0
unknown function (ip: 0x12062d2b3)
Allocations: 3377471 (Pool: 3375868; Big: 1603); GC: 5

StackOverflowError in `JavaCall.init` for Julia 1.1.0

               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.1.0 (2019-01-21)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> using JavaCall

julia> JavaCall.init(["-Xmx128M"])

signal (11): Segmentation fault: 11
in expression starting at no file:0
unknown function (ip: 0x122b242b3)
Allocations: 2501680 (Pool: 2501183; Big: 497); GC: 4
ERROR: StackOverflowError:
Stacktrace:
 [1] init(::Array{String,1}) at /Users/rene/.julia/packages/JavaCall/toamy/src/jvm.jl:176
 [2] top-level scope at none:0

How to load a custom class?

I'm probably missing something obvious here.......

julia> jcall(jlm, "getAlertCountByOwnerId", jlong, (JString,), "1")
ERROR: Class Not Found com/domo/api/alerts/v3/impl
 in _metaclass(::Symbol) at /Users/jacobquinn/.julia/v0.5/JavaCall/src/core.jl:233
 in metaclass(::Symbol) at /Users/jacobquinn/.julia/v0.5/JavaCall/src/core.jl:239
 in jcall(::Type{JavaCall.JavaObject{Symbol("com.domo.api.alerts.v3.impl")}}, ::String, ::Type{T}, ::Tuple{DataType}, ::String, ::Vararg{String,N}) at /Users/jacobquinn/.julia/v0.5/JavaCall/src/core.jl:129

This is just a random class that should be "running"/loaded. What's the process for calling a custom class?

Finding JDK 12

javahome_winreg is unable to find my JDK, because it is not looking at the right registry key. For me, JavaHome is in Computer\HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\12.0.1. It looks like the JDK "key" is not sought for by this package.

(I don't have the time right now to convert this into a PR, but I may in the future.)

Segfault when calling non-existing method (on `geterror`)

Let's take a simple example:

julia> using JavaCall
Found libjvm @ /usr/lib/jvm/default-java/jre/lib/amd64/server

julia> JavaCall.init(["-ea", "-Xmx1024M"])
JNINativeInterface(Ptr{Void} @0x0000000000000000...

julia> jlm = @jimport "java.lang.Math"
JavaObject{symbol("java.lang.Math")} (constructor with 2 methods)

julia> jcall(jlm, "sin", jdouble, (jdouble,), pi/2)
1.0

So code is valid, correct result is returned.

Now I make an error in method name, calling sin111 instead of sin:

julia> jcall(jlm, "sin111", jdouble, (jdouble,), pi/2)

signal (11): Segmentation fault
unknown function (ip: 732001880)
unknown function (ip: 729411466)
unknown function (ip: 729353813)
geterror at /home/<username>/.julia/v0.3/JavaCall/src/JavaCall.jl:215
jcall at /home/<username>/.julia/v0.3/JavaCall/src/JavaCall.jl:233
jl_apply_generic at /usr/local/julia03/bin/../lib/julia/libjulia.so (unknown line)
...

Julia halts due to segmentation fault. Same error occurs even if method name is correct, but types of parameters are wrong, e.g. if we call jcall(jlm, "sin", jint, (jdouble,), pi/2)

For reference, error happens in geterror function, specifically on line:

res = ccall(jnifunc.CallObjectMethod, Ptr{Void}, (Ptr{JNIEnv}, Ptr{Void}, Ptr{Void}), penv, jthrow, jmethodId)

So looks like a problem with pointers, though I wasn't able to follow all levels of indirection.


java version "1.7.0_76" (HotSpot 64-Bit Server VM)
julia version 0.3.8
JavaCall version 0.2.2 (commit 39e2ff9358)

union would crash after init

after using JavaCall; JavaCall.init()
the following code would crash

union([1 for a in 1:1000]...)

(after using JavaCall and before JavaCall.init() won't)

linux 4.19.2
julia version 1.0.1
JavaCall v0.7.1

ldd julia:

    linux-vdso.so.1
    libjulia.so.1 => /usr/bin/../lib/libjulia.so.1
    libdl.so.2 => /usr/bin/../lib/libdl.so.2
    librt.so.1 => /usr/bin/../lib/librt.so.1
    libpthread.so.0 => /usr/bin/../lib/libpthread.so.0
    libc.so.6 => /usr/bin/../lib/libc.so.6
    libLLVM-6.0.so => /usr/bin/../lib/julia/libLLVM-6.0.so
    libstdc++.so.6 => /usr/bin/../lib/julia/libstdc++.so.6
    libm.so.6 => /usr/bin/../lib/libm.so.6
    libgcc_s.so.1 => /usr/bin/../lib/julia/libgcc_s.so.1
    /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2

Ptr returned for double[][] return type

When I do an example method call where the return type is double[][], I get the following output

  julia> jcall(obj, "getDoubles", Array{Array{jdouble, 1}, 1}, ())
  Ptr{Void} @0x0000000008ff5340

[OSX] using JavaCall works, JavaCall.init fails

I am running Julia 0.5.2 on macOS Sierra with Oracle's JDK 8 (121) installed.

My /usr/libexec/java_home points to the correct place

shell> /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home

And my java works:

shell> /usr/bin/java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

The following call therefore works:

julia> using JavaCall
Loaded /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/server/libjvm.dylib

Alas, the subsequent call fails:

julia> JavaCall.init()
signal (11): Segmentation fault: 11
while loading no file, in expression starting on line 0
unknown function (ip: 0x3162db2b3)
Allocations: 2823173 (Pool: 2822149; Big: 1024); GC: 2
No Java runtime present, requesting install.

Followed by the classic macOS popup indicating that Apple's Java (i.e. 6) is required but missing.

Any clue why this could happen? (I have to mention that this is fresh new system/OS, Java 6 was never installed/deleted after some OS upgrade)

Tests fail on julia v0.5 nightly

Running Pkg.test leads to the folowing error:

julia> versioninfo()
Julia Version 0.5.0-dev+4987
Commit 3ac1e62* (2016-06-28 18:44 UTC)
Platform Info:
  System: PLinux (x86_64-unknown-linux-gnu)
  CPU: Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.7.1 (ORCJIT, broadwell)

julia> Pkg.test("JavaCall")
INFO: Testing JavaCall
Loaded /usr/lib/jvm/jdk1.8.0_91/jre/lib/amd64/server/libjvm.so
Julia Version 0.5.0-dev+4987
Commit 3ac1e62* (2016-06-28 18:44 UTC)
Platform Info:
  System: Linux (x86_64-unknown-linux-gnu)
  CPU: Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.7.1 (ORCJIT, broadwell)
[Dynamic-linking native method java.lang.Object.registerNatives ... JNI]
[Registering JNI native method java.lang.Object.hashCode]
[Registering JNI native method java.lang.Object.wait]
[Registering JNI native method java.lang.Object.notify]
[Registering JNI native method java.lang.Object.notifyAll]
[Registering JNI native method java.lang.Object.clone]
[Dynamic-linking native method java.lang.System.registerNatives ... JNI]
[Registering JNI native method java.lang.System.currentTimeMillis]
[Registering JNI native method java.lang.System.nanoTime]
[Registering JNI native method java.lang.System.arraycopy]
[Dynamic-linking native method java.lang.Thread.registerNatives ... JNI]
[Registering JNI native method java.lang.Thread.start0]
[Registering JNI native method java.lang.Thread.stop0]
[Registering JNI native method java.lang.Thread.isAlive]
[Registering JNI native method java.lang.Thread.suspend0]
[Registering JNI native method java.lang.Thread.resume0]
[Registering JNI native method java.lang.Thread.setPriority0]
[Registering JNI native method java.lang.Thread.yield]
[Registering JNI native method java.lang.Thread.sleep]
[Registering JNI native method java.lang.Thread.currentThread]
[Registering JNI native method java.lang.Thread.countStackFrames]
[Registering JNI native method java.lang.Thread.interrupt0]
[Registering JNI native method java.lang.Thread.isInterrupted]
[Registering JNI native method java.lang.Thread.holdsLock]
[Registering JNI native method java.lang.Thread.getThreads]
[Registering JNI native method java.lang.Thread.dumpThreads]
[Registering JNI native method java.lang.Thread.setNativeName]
[Dynamic-linking native method java.security.AccessController.getStackAccessControlContext ... JNI]
[Dynamic-linking native method java.security.AccessController.getInheritedAccessControlContext ... JNI]
[Dynamic-linking native method java.lang.Class.registerNatives ... JNI]
[Registering JNI native method java.lang.Class.getName0]
[Registering JNI native method java.lang.Class.getSuperclass]
[Registering JNI native method java.lang.Class.getInterfaces0]
[Registering JNI native method java.lang.Class.isInterface]
[Registering JNI native method java.lang.Class.getSigners]
[Registering JNI native method java.lang.Class.setSigners]
[Registering JNI native method java.lang.Class.isArray]
[Registering JNI native method java.lang.Class.isPrimitive]
[Registering JNI native method java.lang.Class.getComponentType]
[Registering JNI native method java.lang.Class.getModifiers]
[Registering JNI native method java.lang.Class.getDeclaredFields0]
[Registering JNI native method java.lang.Class.getDeclaredMethods0]
[Registering JNI native method java.lang.Class.getDeclaredConstructors0]
[Registering JNI native method java.lang.Class.getProtectionDomain0]
[Registering JNI native method java.lang.Class.getDeclaredClasses0]
[Registering JNI native method java.lang.Class.getDeclaringClass0]
[Registering JNI native method java.lang.Class.getGenericSignature0]
[Registering JNI native method java.lang.Class.getRawAnnotations]
[Registering JNI native method java.lang.Class.getConstantPool]
[Registering JNI native method java.lang.Class.desiredAssertionStatus0]
[Registering JNI native method java.lang.Class.getEnclosingMethod0]
[Registering JNI native method java.lang.Class.getRawTypeAnnotations]
[Dynamic-linking native method java.lang.ClassLoader.registerNatives ... JNI]
[Registering JNI native method java.lang.ClassLoader.retrieveDirectives]
[Dynamic-linking native method java.security.AccessController.doPrivileged ... JNI]
[Dynamic-linking native method java.lang.Class.forName0 ... JNI]
[Dynamic-linking native method sun.misc.Unsafe.registerNatives ... JNI]
[Registering JNI native method sun.misc.Unsafe.getObject]
[Registering JNI native method sun.misc.Unsafe.putObject]
[Registering JNI native method sun.misc.Unsafe.getObjectVolatile]
[Registering JNI native method sun.misc.Unsafe.putObjectVolatile]
[Registering JNI native method sun.misc.Unsafe.getBoolean]
[Registering JNI native method sun.misc.Unsafe.putBoolean]
[Registering JNI native method sun.misc.Unsafe.getBooleanVolatile]
[Registering JNI native method sun.misc.Unsafe.putBooleanVolatile]
[Registering JNI native method sun.misc.Unsafe.getByte]
[Registering JNI native method sun.misc.Unsafe.putByte]
[Registering JNI native method sun.misc.Unsafe.getByteVolatile]
[Registering JNI native method sun.misc.Unsafe.putByteVolatile]
[Registering JNI native method sun.misc.Unsafe.getShort]
[Registering JNI native method sun.misc.Unsafe.putShort]
[Registering JNI native method sun.misc.Unsafe.getShortVolatile]
[Registering JNI native method sun.misc.Unsafe.putShortVolatile]
[Registering JNI native method sun.misc.Unsafe.getChar]
[Registering JNI native method sun.misc.Unsafe.putChar]
[Registering JNI native method sun.misc.Unsafe.getCharVolatile]
[Registering JNI native method sun.misc.Unsafe.putCharVolatile]
[Registering JNI native method sun.misc.Unsafe.getInt]
[Registering JNI native method sun.misc.Unsafe.putInt]
[Registering JNI native method sun.misc.Unsafe.getIntVolatile]
[Registering JNI native method sun.misc.Unsafe.putIntVolatile]
[Registering JNI native method sun.misc.Unsafe.getLong]
[Registering JNI native method sun.misc.Unsafe.putLong]
[Registering JNI native method sun.misc.Unsafe.getLongVolatile]
[Registering JNI native method sun.misc.Unsafe.putLongVolatile]
[Registering JNI native method sun.misc.Unsafe.getFloat]
[Registering JNI native method sun.misc.Unsafe.putFloat]
[Registering JNI native method sun.misc.Unsafe.getFloatVolatile]
[Registering JNI native method sun.misc.Unsafe.putFloatVolatile]
[Registering JNI native method sun.misc.Unsafe.getDouble]
[Registering JNI native method sun.misc.Unsafe.putDouble]
[Registering JNI native method sun.misc.Unsafe.getDoubleVolatile]
[Registering JNI native method sun.misc.Unsafe.putDoubleVolatile]
[Registering JNI native method sun.misc.Unsafe.getByte]
[Registering JNI native method sun.misc.Unsafe.putByte]
[Registering JNI native method sun.misc.Unsafe.getShort]
[Registering JNI native method sun.misc.Unsafe.putShort]
[Registering JNI native method sun.misc.Unsafe.getChar]
[Registering JNI native method sun.misc.Unsafe.putChar]
[Registering JNI native method sun.misc.Unsafe.getInt]
[Registering JNI native method sun.misc.Unsafe.putInt]
[Registering JNI native method sun.misc.Unsafe.getLong]
[Registering JNI native method sun.misc.Unsafe.putLong]
[Registering JNI native method sun.misc.Unsafe.getFloat]
[Registering JNI native method sun.misc.Unsafe.putFloat]
[Registering JNI native method sun.misc.Unsafe.getDouble]
[Registering JNI native method sun.misc.Unsafe.putDouble]
[Registering JNI native method sun.misc.Unsafe.getAddress]
[Registering JNI native method sun.misc.Unsafe.putAddress]
[Registering JNI native method sun.misc.Unsafe.allocateMemory]
[Registering JNI native method sun.misc.Unsafe.reallocateMemory]
[Registering JNI native method sun.misc.Unsafe.freeMemory]
[Registering JNI native method sun.misc.Unsafe.objectFieldOffset]
[Registering JNI native method sun.misc.Unsafe.staticFieldOffset]
[Registering JNI native method sun.misc.Unsafe.staticFieldBase]
[Registering JNI native method sun.misc.Unsafe.ensureClassInitialized]
[Registering JNI native method sun.misc.Unsafe.arrayBaseOffset]
[Registering JNI native method sun.misc.Unsafe.arrayIndexScale]
[Registering JNI native method sun.misc.Unsafe.addressSize]
[Registering JNI native method sun.misc.Unsafe.pageSize]
[Dynamic-linking native method java.lang.Throwable.fillInStackTrace ... JNI]
[Registering JNI native method sun.misc.Unsafe.getObject]
[Registering JNI native method sun.misc.Unsafe.putObject]
[Registering JNI native method sun.misc.Unsafe.getObjectVolatile]
[Registering JNI native method sun.misc.Unsafe.putObjectVolatile]
[Registering JNI native method sun.misc.Unsafe.getBoolean]
[Registering JNI native method sun.misc.Unsafe.putBoolean]
[Registering JNI native method sun.misc.Unsafe.getBooleanVolatile]
[Registering JNI native method sun.misc.Unsafe.putBooleanVolatile]
[Registering JNI native method sun.misc.Unsafe.getByte]
[Registering JNI native method sun.misc.Unsafe.putByte]
[Registering JNI native method sun.misc.Unsafe.getByteVolatile]
[Registering JNI native method sun.misc.Unsafe.putByteVolatile]
[Registering JNI native method sun.misc.Unsafe.getShort]
[Registering JNI native method sun.misc.Unsafe.putShort]
[Registering JNI native method sun.misc.Unsafe.getShortVolatile]
[Registering JNI native method sun.misc.Unsafe.putShortVolatile]
[Registering JNI native method sun.misc.Unsafe.getChar]
[Registering JNI native method sun.misc.Unsafe.putChar]
[Registering JNI native method sun.misc.Unsafe.getCharVolatile]
[Registering JNI native method sun.misc.Unsafe.putCharVolatile]
[Registering JNI native method sun.misc.Unsafe.getInt]
[Registering JNI native method sun.misc.Unsafe.putInt]
[Registering JNI native method sun.misc.Unsafe.getIntVolatile]
[Registering JNI native method sun.misc.Unsafe.putIntVolatile]
[Registering JNI native method sun.misc.Unsafe.getLong]
[Registering JNI native method sun.misc.Unsafe.putLong]
[Registering JNI native method sun.misc.Unsafe.getLongVolatile]
[Registering JNI native method sun.misc.Unsafe.putLongVolatile]
[Registering JNI native method sun.misc.Unsafe.getFloat]
[Registering JNI native method sun.misc.Unsafe.putFloat]
[Registering JNI native method sun.misc.Unsafe.getFloatVolatile]
[Registering JNI native method sun.misc.Unsafe.putFloatVolatile]
[Registering JNI native method sun.misc.Unsafe.getDouble]
[Registering JNI native method sun.misc.Unsafe.putDouble]
[Registering JNI native method sun.misc.Unsafe.getDoubleVolatile]
[Registering JNI native method sun.misc.Unsafe.putDoubleVolatile]
[Registering JNI native method sun.misc.Unsafe.getByte]
[Registering JNI native method sun.misc.Unsafe.putByte]
[Registering JNI native method sun.misc.Unsafe.getShort]
[Registering JNI native method sun.misc.Unsafe.putShort]
[Registering JNI native method sun.misc.Unsafe.getChar]
[Registering JNI native method sun.misc.Unsafe.putChar]
[Registering JNI native method sun.misc.Unsafe.getInt]
[Registering JNI native method sun.misc.Unsafe.putInt]
[Registering JNI native method sun.misc.Unsafe.getLong]
[Registering JNI native method sun.misc.Unsafe.putLong]
[Registering JNI native method sun.misc.Unsafe.getFloat]
[Registering JNI native method sun.misc.Unsafe.putFloat]
[Registering JNI native method sun.misc.Unsafe.getDouble]
[Registering JNI native method sun.misc.Unsafe.putDouble]
[Registering JNI native method sun.misc.Unsafe.getAddress]
[Registering JNI native method sun.misc.Unsafe.putAddress]
[Registering JNI native method sun.misc.Unsafe.allocateMemory]
[Registering JNI native method sun.misc.Unsafe.reallocateMemory]
[Registering JNI native method sun.misc.Unsafe.freeMemory]
[Registering JNI native method sun.misc.Unsafe.objectFieldOffset]
[Registering JNI native method sun.misc.Unsafe.staticFieldOffset]
[Registering JNI native method sun.misc.Unsafe.staticFieldBase]
[Registering JNI native method sun.misc.Unsafe.ensureClassInitialized]
[Registering JNI native method sun.misc.Unsafe.arrayBaseOffset]
[Registering JNI native method sun.misc.Unsafe.arrayIndexScale]
[Registering JNI native method sun.misc.Unsafe.addressSize]
[Registering JNI native method sun.misc.Unsafe.pageSize]
[Registering JNI native method sun.misc.Unsafe.defineClass]
[Registering JNI native method sun.misc.Unsafe.allocateInstance]
[Registering JNI native method sun.misc.Unsafe.monitorEnter]
[Registering JNI native method sun.misc.Unsafe.monitorExit]
[Registering JNI native method sun.misc.Unsafe.tryMonitorEnter]
[Registering JNI native method sun.misc.Unsafe.throwException]
[Registering JNI native method sun.misc.Unsafe.compareAndSwapObject]
[Registering JNI native method sun.misc.Unsafe.compareAndSwapInt]
[Registering JNI native method sun.misc.Unsafe.compareAndSwapLong]
[Registering JNI native method sun.misc.Unsafe.putOrderedObject]
[Registering JNI native method sun.misc.Unsafe.putOrderedInt]
[Registering JNI native method sun.misc.Unsafe.putOrderedLong]
[Registering JNI native method sun.misc.Unsafe.park]
[Registering JNI native method sun.misc.Unsafe.unpark]
[Registering JNI native method sun.misc.Unsafe.getLoadAverage]
[Registering JNI native method sun.misc.Unsafe.copyMemory]
[Registering JNI native method sun.misc.Unsafe.setMemory]
[Registering JNI native method sun.misc.Unsafe.defineAnonymousClass]
[Registering JNI native method sun.misc.Unsafe.shouldBeInitialized]
[Registering JNI native method sun.misc.Unsafe.loadFence]
[Registering JNI native method sun.misc.Unsafe.storeFence]
[Registering JNI native method sun.misc.Unsafe.fullFence]
[Dynamic-linking native method sun.reflect.Reflection.getCallerClass ... JNI]
[Dynamic-linking native method java.lang.Class.getPrimitiveClass ... JNI]
[Dynamic-linking native method java.lang.Float.floatToRawIntBits ... JNI]
[Dynamic-linking native method java.lang.Double.doubleToRawLongBits ... JNI]
[Dynamic-linking native method java.lang.Double.longBitsToDouble ... JNI]
[Dynamic-linking native method sun.misc.VM.initialize ... JNI]
[Dynamic-linking native method java.lang.System.initProperties ... JNI]
[Dynamic-linking native method java.lang.String.intern ... JNI]
[Dynamic-linking native method java.lang.Object.getClass ... JNI]
[Dynamic-linking native method sun.reflect.Reflection.getClassAccessFlags ... JNI]
[Dynamic-linking native method sun.reflect.NativeConstructorAccessorImpl.newInstance0 ... JNI]
[Dynamic-linking native method java.lang.Runtime.maxMemory ... JNI]
[Dynamic-linking native method java.io.FileInputStream.initIDs ... JNI]
[Dynamic-linking native method java.io.FileDescriptor.initIDs ... JNI]
[Dynamic-linking native method java.io.FileOutputStream.initIDs ... JNI]
[Dynamic-linking native method java.security.AccessController.doPrivileged ... JNI]
[Dynamic-linking native method java.lang.System.setIn0 ... JNI]
[Dynamic-linking native method java.util.concurrent.atomic.AtomicLong.VMSupportsCS8 ... JNI]
[Dynamic-linking native method java.lang.System.setOut0 ... JNI]
[Dynamic-linking native method java.lang.System.setErr0 ... JNI]
[Dynamic-linking native method java.io.UnixFileSystem.initIDs ... JNI]
[Dynamic-linking native method java.lang.System.mapLibraryName ... JNI]
[Dynamic-linking native method java.lang.ClassLoader.findBuiltinLib ... JNI]
[Dynamic-linking native method java.io.UnixFileSystem.getBooleanAttributes0 ... JNI]
[Dynamic-linking native method java.io.UnixFileSystem.canonicalize0 ... JNI]
[Dynamic-linking native method java.lang.ClassLoader$NativeLibrary.load ... JNI]
[Dynamic-linking native method sun.misc.Signal.findSignal ... JNI]
[Dynamic-linking native method sun.misc.Signal.handle0 ... JNI]
[Dynamic-linking native method java.lang.Compiler.registerNatives ... JNI]
[Registering JNI native method java.lang.Compiler.compileClass]
[Registering JNI native method java.lang.Compiler.compileClasses]
[Registering JNI native method java.lang.Compiler.command]
[Registering JNI native method java.lang.Compiler.enable]
[Registering JNI native method java.lang.Compiler.disable]
[Dynamic-linking native method java.lang.Class.isAssignableFrom ... JNI]
[Dynamic-linking native method java.io.FileInputStream.open0 ... JNI]
[Dynamic-linking native method java.io.FileInputStream.readBytes ... JNI]
[Dynamic-linking native method java.io.FileInputStream.available ... JNI]
[Dynamic-linking native method java.lang.reflect.Array.newArray ... JNI]
[Dynamic-linking native method java.io.FileInputStream.close0 ... JNI]
[Dynamic-linking native method java.io.UnixFileSystem.list ... JNI]
[Dynamic-linking native method java.lang.Runtime.availableProcessors ... JNI]
[Dynamic-linking native method sun.misc.URLClassPath.getLookupCacheURLs ... JNI]
[Dynamic-linking native method java.lang.invoke.MethodHandleNatives.registerNatives ... JNI]
[Registering JNI native method java.lang.invoke.MethodHandleNatives.init]
[Registering JNI native method java.lang.invoke.MethodHandleNatives.expand]
[Registering JNI native method java.lang.invoke.MethodHandleNatives.resolve]
[Registering JNI native method java.lang.invoke.MethodHandleNatives.getConstant]
[Registering JNI native method java.lang.invoke.MethodHandleNatives.getNamedCon]
[Registering JNI native method java.lang.invoke.MethodHandleNatives.getMembers]
[Registering JNI native method java.lang.invoke.MethodHandleNatives.objectFieldOffset]
[Registering JNI native method java.lang.invoke.MethodHandleNatives.setCallSiteTargetNormal]
[Registering JNI native method java.lang.invoke.MethodHandleNatives.setCallSiteTargetVolatile]
[Registering JNI native method java.lang.invoke.MethodHandleNatives.staticFieldOffset]
[Registering JNI native method java.lang.invoke.MethodHandleNatives.staticFieldBase]
[Registering JNI native method java.lang.invoke.MethodHandleNatives.getMemberVMInfo]
[Registering JNI native method java.lang.invoke.MethodHandle.invoke]
[Registering JNI native method java.lang.invoke.MethodHandle.invokeExact]
[Dynamic-linking native method java.io.FileOutputStream.open0 ... JNI]
[Dynamic-linking native method java.io.FileOutputStream.writeBytes ... JNI]
[Dynamic-linking native method java.io.FileOutputStream.close0 ... JNI]
[Dynamic-linking native method java.lang.ClassLoader.findLoadedClass0 ... JNI]
[Dynamic-linking native method java.lang.ClassLoader.findBootstrapClass ... JNI]
[Dynamic-linking native method java.lang.ClassLoader$NativeLibrary.find ... JNI]
[Dynamic-linking native method java.security.AccessController.doPrivileged ... JNI]
[Dynamic-linking native method java.util.zip.ZipFile.initIDs ... JNI]
[Dynamic-linking native method java.io.UnixFileSystem.getLength ... JNI]
[Dynamic-linking native method sun.misc.Perf.registerNatives ... JNI]
[Registering JNI native method sun.misc.Perf.attach]
[Registering JNI native method sun.misc.Perf.detach]
[Registering JNI native method sun.misc.Perf.createLong]
[Registering JNI native method sun.misc.Perf.createByteArray]
[Registering JNI native method sun.misc.Perf.highResCounter]
[Registering JNI native method sun.misc.Perf.highResFrequency]
[Dynamic-linking native method java.lang.ClassLoader.defineClass1 ... JNI]
Error During Test
  Test threw an exception of type UndefRefError
  Expression: 10 == jcall(T,"testShort",jshort,(jshort,),10)
  UndefRefError: access to undefined reference
   in _jcall(::JavaCall.JavaMetaClass{:Test}, ::Ptr{Void}, ::Ptr{Void}, ::Type{Int16}, ::Tuple{DataType}, ::Int64, ::Vararg{Int64,N}) at /home/nishanth/.julia/v0.5/JavaCall/src/core.jl:220
   in jcall(::Type{JavaCall.JavaObject{:Test}}, ::String, ::Type{T}, ::Tuple{DataType}, ::Int64, ::Vararg{Int64,N}) at /home/nishanth/.julia/v0.5/JavaCall/src/core.jl:141
   in include_from_node1(::String) at ./loading.jl:426
   in process_options(::Base.JLOptions) at ./client.jl:266
   in _start() at ./client.jl:322
ERROR: LoadError: There was an error during testing
 in record(::Base.Test.FallbackTestSet, ::Base.Test.Error) at ./test.jl:399
 in do_test(::Base.Test.Threw, ::Expr) at ./test.jl:282
 in include_from_node1(::String) at ./loading.jl:426
 in process_options(::Base.JLOptions) at ./client.jl:266
 in _start() at ./client.jl:322
while loading /home/nishanth/.julia/v0.5/JavaCall/test/runtests.jl, in expression starting on line 25
==============================[ ERROR: JavaCall ]===============================

failed process: Process(`/home/nishanth/tmp/julia-3ac1e62d28/bin/julia -Cx86-64 -J/home/nishanth/tmp/julia-3ac1e62d28/lib/julia/sys.so --compile=yes --depwarn=yes --check-bounds=yes --code-coverage=none --color=yes /home/nishanth/.julia/v0.5/JavaCall/test/runtests.jl`, ProcessExited(1)) [1]

================================================================================
ERROR: JavaCall had test errors
 in #test#49(::Bool, ::Function, ::Array{AbstractString,1}) at ./pkg/entry.jl:694
 in (::Base.Pkg.Entry.#kw##test)(::Array{Any,1}, ::Base.Pkg.Entry.#test, ::Array{AbstractString,1}) at ./null:0
 in (::Base.Pkg.Dir.##2#3{Array{Any,1},Base.Pkg.Entry.#test,Tuple{Array{AbstractString,1}}})() at ./pkg/dir.jl:31
 in cd(::Base.Pkg.Dir.##2#3{Array{Any,1},Base.Pkg.Entry.#test,Tuple{Array{AbstractString,1}}}, ::String) at ./file.jl:59
 in #cd#1(::Array{Any,1}, ::Function, ::Function, ::Array{AbstractString,1}, ::Vararg{Array{AbstractString,1},N}) at ./pkg/dir.jl:31
 in (::Base.Pkg.Dir.#kw##cd)(::Array{Any,1}, ::Base.Pkg.Dir.#cd, ::Function, ::Array{AbstractString,1}, ::Vararg{Array{AbstractString,1},N}) at ./null:0
 in #test#3(::Bool, ::Function, ::String, ::Vararg{String,N}) at ./pkg/pkg.jl:255
 in test(::String, ::Vararg{String,N}) at ./pkg/pkg.jl:255
 in eval(::Module, ::Any) at ./boot.jl:234
 in macro expansion at ./REPL.jl:92 [inlined]
 in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46

Support Generic classes

Currently the JavaCall layer does not deal with type parameters at all, primarily due to the fact that they are erased at runtime by the JVM. However, in some scenarios, it may be useful to make information about type parameters available to the Julia layer.

What form this support should take is unclear at the moment.

cc: @dfdx cf: #11

export addClassPath and addOpts

Is it possible to export those two functions?

I need to use differents Java packages in different julia modules.
I’d like to add all paths I need with addClassPath before the init.

Support for JNI 1.8

JavaCall causes an error when using it with JNI versions later than 1.6. The error displayed is ERROR: assertion failed: jni_version == JNI_VERSION_1_6. Since JDK 1.8, JNI version 1.8 is included, making this assertion always fail when using JavaCall on *.jar files created with this version of Java.

Line 457 In src/JavaCall.jl (@assert ccall(jnifunc.GetVersion, Cint, (Ptr{JNIEnv},), penv) == JNI_VERSION_1_6) causes the error.

Changing the line to @assert jni_version >= JNI_VERSION_1_6 #Also allowing jni 1.8 solves the issue. I can't find any changes since 1.6, and after a little testing, using JNI 1.8 seems to be working fine.

Is convert_args safe with finalizer?

Now JavaCall tries to use saved_args to keep reference of JavaObject while pass arg.ptr into JNI FFI.

JavaCall.jl/src/core.jl

Lines 244 to 248 in d6c3678

savedArgs, convertedArgs = convert_args(argtypes, args...)
result = ccall(callmethod, Ptr{Nothing}, (Ptr{JNIEnv}, Ptr{Nothing}, Ptr{Nothing}, Ptr{Nothing}),
penv, obj.ptr, jmethodId, convertedArgs)
result==C_NULL && geterror()
return convert_result(rettype, result)

But saved_args is not referenced after it created, it might be garbage collected at any time (even before ccall).
I learnt from this gc would only occurs when allocates memory (so current code might work now), but it is hard to trace memory allocation.

Is there any better solution that telling gc not to collect saved_args?

Random segfaults (pointers to objects become invalid?)

Recently I got a new source for segmentation faults. This time, however, errors are not strictly reproducible, but somewhat random. Below is an example Julia session with actual code that I'm working on. In general, when done carefully, following sequence of commands does NOT produce any error, resulting in valid references to Java objects. Sometimes, however, things like in this session happen.

First, I load my code by including facade file "core.jl":

julia> include("core.jl")
Loaded /usr/lib/jvm/jdk1.7.0_79/jre/lib/amd64/server/libjvm.so
demo (generic function with 1 method)

Then I create some objects with references to Java objects, and it works perfectly fine:

julia> sc = SparkContext()
Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties
15/08/08 01:26:16 INFO SparkContext: Running Spark version 1.3.1
...
SparkContext(JavaObject{symbol("org.apache.spark.api.java.JavaSparkContext")}(Ptr{Void} @0x000000000845c048))

julia> java_rdd = text_file(sc, "file:///var/log/syslog")
15/08/08 01:26:36 INFO MemoryStore: ensureFreeSpace(182921) called with curMem=0, maxMem=515553361
...
JavaRDD(JavaObject{symbol("org.apache.spark.api.java.JavaRDD")}(Ptr{Void} @0x000000000845c058))

But later code with references to just created objects may unexpectedly fail with NullPointerException:

julia> rdd = PipelinedRDD(java_rdd, identity)
Exception in thread "main" java.lang.NullPointerException
    at org.apache.spark.api.java.JavaRDD$.toRDD(JavaRDD.scala:197)
    at org.apache.spark.api.julia.JuliaRDD$.fromJavaRDD(JuliaRDD.scala:176)
    at org.apache.spark.api.julia.JuliaRDD.fromJavaRDD(JuliaRDD.scala)
ERROR: Error calling Java: java.lang.NullPointerException
 in error at error.jl:21
 in geterror at /home/<username>/.julia/v0.3/JavaCall/src/core.jl:206
 in _jcall at /home/<username>/.julia/v0.3/JavaCall/src/core.jl:174
 in jcall at /home/<username>/.julia/v0.3/JavaCall/src/core.jl:110
 in PipelinedRDD at /home/<username>/.julia/v0.3/Sparta/src/rdd.jl:19

And when trying to repeat calls that were valid 2 minutes ago result in a segmentation fault:

julia> java_rdd = text_file(sc, "file:///var/log/syslog")

signal (11): Segmentation fault
unknown function (ip: -947006856)
unknown function (ip: -946938247)
_jcall at /home/<username>/.julia/v0.3/JavaCall/src/core.jl:173
jl_apply_generic at /usr/local/julia03/bin/../lib/julia/libjulia.so (unknown line)
jl_f_apply at /usr/local/julia03/bin/../lib/julia/libjulia.so (unknown line)
jcall at /home/<username>/.julia/v0.3/JavaCall/src/core.jl:124
jl_apply_generic at /usr/local/julia03/bin/../lib/julia/libjulia.so (unknown line)
text_file at /home/<username>/.julia/v0.3/Sparta/src/context.jl:13
jl_apply_generic at /usr/local/julia03/bin/../lib/julia/libjulia.so (unknown line)
unknown function (ip: -508562872)
unknown function (ip: -508566343)
unknown function (ip: -508565685)
unknown function (ip: -508561350)
unknown function (ip: -508568005)
unknown function (ip: -508498911)
jl_f_top_eval at /usr/local/julia03/bin/../lib/julia/libjulia.so (unknown line)
eval_user_input at REPL.jl:53
jlcall_eval_user_input_20017 at  (unknown line)
jl_apply_generic at /usr/local/julia03/bin/../lib/julia/libjulia.so (unknown line)
anonymous at task.jl:95
jl_handle_stack_switch at /usr/local/julia03/bin/../lib/julia/libjulia.so (unknown line)
julia_trampoline at /usr/local/julia03/bin/../lib/julia/libjulia.so (unknown line)
unknown function (ip: 4199805)
__libc_start_main at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
unknown function (ip: 4199861)
Segmentation fault

So it looks like references to some Java objects become invalid (because of garbage collection?) and all kinds of fun happen.

I understand that an issue formulated in such a way is terribly hard to debug, so I'm ready to provide any needed information. Alternatively, you can reproduce it yourself using special branch (segfault-demo) in my repository (https://github.com/dfdx/Sparta.jl). To do so:

  1. Clone repository and checkout the branch: git clone https://github.com/dfdx/Sparta.jl; cd Sparta; git checkout segfault-demo
  2. Build Java classes (assuming you have Maven installed): cd mvn/sparta; mvn clean package
  3. Start Julia session and perform operations like above several times, may be with some pauses.

I was able to reproduce it with Oracle and OpenJDK 1.7, on Julia 0.3 and 0.4.

Invoking a method that modifies an input parameter

I am invoking a Java method that accepts an array as a parameter and returns an int, something like int method(byte[] out). method is modifying the out parameter which I would like to pick Julia side.

On Julia side I have:

jout = Array{UInt8}(undef, 64)
jcall(object, "method", jint, (Array{jbyte,1}), jout)

But what I see is that jout is not affected by the invocation. How do I implemented this invocation pattern with JavaCall?

Proposal: jdcall and jtypeforclass

  1. Now the get class for name is compatible with Array and primitive types

JavaCall.jl/src/convert.jl

Lines 321 to 325 in d6c3678

function narrow(obj::JavaObject)
c = jcall(obj,"getClass", @jimport(java.lang.Class), ())
t = jcall(c, "getName", JString, ())
return convert(JavaObject{Symbol(t)}, obj)
end

JavaCall.jl/src/reflect.jl

Lines 163 to 168 in d6c3678

function classforname(name::String)
thread = jcall(JThread, "currentThread", JThread, ())
loader = jcall(thread, "getContextClassLoader", JClassLoader, ())
return jcall(JClass, "forName", JClass, (JString, jboolean, JClassLoader),
name, true, loader)
end

This method may help

function jtypeforclass(cls::JClass)
    isarray(cls) = jcall(cls, "isArray", jboolean, ()) != 0x00
    if isarray(cls)
        jcomponentcls = jcall(cls, "getComponentType", JClass, ())
        return Array{jtypeforclass(jcomponentcls), 1}
    end
    name = getname(cls)
    if name == "void"
        Nothing
    elseif name == "boolean"
        jboolean
    elseif name == "char"
        jchar
    elseif name == "short"
        jshort
    elseif name == "float"
        jfloat
    elseif name == "double"
        jdouble
    elseif name == "int"
        jint
    elseif name == "long"
        jlong
    else
        JavaObject{Symbol(name)}
    end
end

and the narrow would be

function narrow(obj::JavaObject)
    c = jcall(obj,"getClass", JClass, ())
    return convert(jtypeforclass(c), obj)
end
narrow(obj::JavaCall.jprimitive) = obj
  1. And it would be possible to call functions without specific return type and argument type
convertible(javatype::Type, juliatype::Type) = hasmethod(convert, Tuple{Type{javatype}, juliatype})

function findmethod(obj::Union{JavaObject{C}, Type{JavaObject{C}}}, name::AbstractString, args...) where C
    allmethods = listmethods(obj, name)
    filter(allmethods) do m
        params = getparametertypes(m)
        if length(params) != length(args)
            return false
        end
        all([convertible(jtypeforclass(c), typeof(a)) for (c, a) in zip(getparametertypes(m), args)])
    end
end

function jdcall(obj::Union{JavaObject{C}, Type{JavaObject{C}}}, name::AbstractString, args...) where C
    matchmethods = findmethod(obj, name, args...)
    if length(matchmethods) == 0
        allmethods = listmethods(obj, name)
        candidates = join(allmethods, "\n  ")
        error("no match methods $name for $obj, candidates are:\n  $candidates")
    elseif length(matchmethods) > 1
        candidates = join(matchmethods, "\n  ")
        error("multiple methods $name for $obj, candidates are:\n  $candidates")
    end
    matchmethod = matchmethods[1]
    rettype = jtypeforclass(getreturntype(matchmethod))
    argstype = tuple(map(jtypeforclass, getparametertypes(matchmethod))...)
    # println("type: $rettype ($argstype)")
    return jcall(obj, name, rettype, argstype, args...)
end

Since narrow and classforname are both exported, so this may be a breaking change, although I think the behavior of the two methods now is strange when it comes to array and/or jint.

Thoughts on JuliaInterop org

Was just wondering if you think it's worth consolidating a few of the interop packages under one org – there are at least 6 by my count and it might be nice to show them off together.

Calling Swing/AWT components with JavaCall on OS X

Hi there,

i would like to call swing/awt components with JavaCall. But there seems to be some thread issues. Frames do not open.
I think this is not an JavaCall issue but an cocoa/JNI thing but maybe someone knows a workaround for JavaCall on OS X?

Thank you in advance.

Best Max

Can not have an inner class as a return type

Using the below code

using JavaCall
classpath="../bin"
JavaCall.init(["-Djava.class.path=$(classpath)"]);
jadder=@jimport javaTest.FourAdderOuter
jout=@jimport javaTest.outStuff
println("Got the stuff here");
myadder=jadder((),)
out=jcall(myadder,"addstuff",jout, (jint,jint,jint,jint),1,2,3,40)

with the two Java classes:

package javaTest;
public class outStuff {
    private int output;
    public int getOutput() {
        return output;
    }
    public void setOutput(int output) {
        this.output = output;
    }
}

and

package javaTest;
public class FourAdderOuter {//implements adderIfc {
    public FourAdderOuter() {
        System.out.println("Generated Adder Outer");
    }
    public outStuff addstuff(int a,int b, int c, int d) {
        outStuff out= new outStuff();       
        out.setOutput(a+b+c+d);
        return out;
    }
}

work just fine.

However if outStuff was an inner class, it breaks, as in the following java class

package javaTest;
public class FourAdder {//implements adderIfc {
    public FourAdder() {
        System.out.println("Generated Adder");
    }
    public class outStuff{
        private int output;
        public int getOutput() {
            return output;
        }
        public void setOutput(int output) {
            this.output = output;
        }
    }
    public outStuff addstuff(int a,int b, int c, int d) {
        outStuff out= new outStuff();       
        out.setOutput(a+b+c+d);
        return out;
    }
}

Using JavaCall

using JavaCall
classpath="../bin"
JavaCall.init(["-Djava.class.path=$(classpath)"]);
jadder=@jimport javaTest.FourAdder
jout=@jimport javaTest.FourAdder.outStuff
myadder=jadder((),)
out=jcall(myadder,"addstuff",jout, (jint,jint,jint,jint),1,2,3,40)

results in the following exception

Exception in thread "main" java.lang.NoSuchMethodError: addstuff
ERROR: Error calling Java: java.lang.NoSuchMethodError: addstuff

Error handling for windows registry read

If Java is not installed, trying to load JavaCall on windows causes: ERROR: LoadError: LoadError: InitError: Could not open registry key

We should trap that and throw a proper error suggesting that the user install Java.

cc: @AndyGreenwell

How to add classpath

This may seem like a silly question but how do I specify the java classpath on JVM init. Say I want to call Java code from some packaged JAR?

jcall a method that returns void

Hello

How do I jcall a method that returns void? I tried jcall(jimported, "methodName" , Void , (<argument types>), <argument values>) but got ERROR: UndefVarError: Void not defined

broken conversion from `java.sql.Date`

At least I think it's broken.

jsd = @jimport(java.sql.Date)((jlong,),0)
convert(DateTime, jsd)  # returns 1969-12-31T20:00:00

I was expecting "1970-01-01T00:00:00". Is this some time zone issue?

There seems to be a problem in JDBC.jl where some time conversions are off by an hour (that's right, 1 hour, not 4).

Path added with `addClassPath` ignored by `init(opts)` method

I tried to do something like this:

JavaCall.addClassPath("/mypath/*")
JavaCall.init(["-Xmx512M"])

It took me a while to understand why my class path was ignored.

You need to do either:

JavaCall.init(["-Xmx512M", "-Djava.class.path=/mypath/*"])

or:

JavaCall.addClassPath("/mypath/*")
JavaCall.addOpts("-Xmx512M")
JavaCall.init()

It would be nice if init(opts) honored paths added via addClassPath (though this raises the question of what to do if the user also includes "-Djava.class.path=..." in opts). Short of that, maybe the docs could mention the possible gotcha.

jar-file inside jar-file

I have a jar-file which packages its libraries in a lib-directory inside itself. The MANIFEST.MF inside the jar allows the libraries to be found.

When I call a class from the jar the library inside it is not found and I get java.lang.NoClassDefFoundError. I have to extract the lib-directory and add it manually to the class path.

How can I add jar-file inside a jar-file to the class path in JavaCall.jl?

JavaCall.init: Segmentation Fault when called from REPL

When calling JavaCall.init from the REPL I get a segmentation fault:

$ java -version
openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1)
OpenJDK 64-Bit Server VM (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1, mixed mode, sharing)
$ julia -version
julia version 1.3.1
$ julia --banner=no
julia> using JavaCall; JavaCall.init(["-Xmx128m"])
Segmentation fault (core dumped)

Thie segmentation fault does not occur from when passed in via -e, -E, or via a file using -i:

$ julia -E "using JavaCall; JavaCall.init([\"Xmx128m\"]); jlm = @jimport java.lang.Math; jcall(jlm, \"sin\", jdouble, (jdouble,), pi/2)"
1.0

The problem also does not occur when using JULIA_COPY_STACKS=yes:

$ JULIA_COPY_STACKS=yes julia --banner=no
julia> using JavaCall; JavaCall.init(["-Xmx128m"])

julia> jlm = @jimport java.lang.Math
JavaObject{Symbol("java.lang.Math")}
julia> jcall(jlm, "sin", jdouble, (jdouble,), pi/2)
1.0

Running gdb exposes the following backtrace:

julia> using JavaCall; JavaCall.init(["-Xmx128m"])

Thread 1 "julia" received signal SIGSEGV, Segmentation fault.
0x00007fffb39e152d in ?? ()
(gdb) bt
#0  0x00007fffb39e152d in ?? ()
#1  0x0000000000000202 in ?? ()
#2  0x00007fffb39e1280 in ?? ()
#3  0x00007fffcd78d2dc in Abstract_VM_Version::_vm_major_version ()
   from /usr/lib/jvm/default-java/lib/server/libjvm.so
#4  0x00007fffcdbe3680 in ?? ()
#5  0x00007fffcd1c0759 in VM_Version::get_processor_features ()
    at ./src/hotspot/cpu/x86/vm_version_x86.cpp:575

Line 575 refers to
https://git.launchpad.net/ubuntu/+source/openjdk-lts/tree/src/hotspot/cpu/x86/vm_version_x86.cpp?h=ubuntu/bionic-updates#n575
Which is supposed to produce a SIGSEGV:
https://bugzilla.redhat.com/show_bug.cgi?id=1572811#c7

When running with JULIA_COPY_STACKS=yes a SIGSEGV is also sent but does not crash julia:

(gdb) set environment JULIA_COPY_STACKS=yes
(gdb) run --banner=no
Starting program: julia --banner=no
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff3365700 (LWP 11951)]
[New Thread 0x7fffe14ba700 (LWP 11952)]
[New Thread 0x7fffe0cb9700 (LWP 11953)]
[New Thread 0x7fffdc4b8700 (LWP 11954)]
[New Thread 0x7fffdbcb7700 (LWP 11955)]
[New Thread 0x7fffd74b6700 (LWP 11956)]
[New Thread 0x7fffd4cb5700 (LWP 11957)]
[New Thread 0x7fffd24b4700 (LWP 11958)]
julia> using JavaCall; JavaCall.init(["-Xmx128m"])

Thread 1 "julia" received signal SIGSEGV, Segmentation fault.
0x00007fffb25e152d in ?? ()
(gdb) continue
Continuing.
[New Thread 0x7fffb240a700 (LWP 11981)]
[New Thread 0x7fffb1680700 (LWP 11982)]
[New Thread 0x7fffb157e700 (LWP 11983)]
[New Thread 0x7fffb0c74700 (LWP 11984)]
[New Thread 0x7fffb0b72700 (LWP 11985)]
[New Thread 0x7fffb0194700 (LWP 11986)]
[New Thread 0x7fffa1fff700 (LWP 11987)]
[New Thread 0x7fffa1efe700 (LWP 11988)]
[New Thread 0x7fffa1dfd700 (LWP 11989)]
[New Thread 0x7fffa1cfc700 (LWP 11990)]
[New Thread 0x7fffa1bfb700 (LWP 11991)]
[New Thread 0x7fffa1afa700 (LWP 11992)]
[New Thread 0x7fffa19f9700 (LWP 11993)]
[New Thread 0x7fffa18f8700 (LWP 11994)]

julia> julia> 5+5
10

Here's a more sane backtrace using a breakpoint:

$ gdb julia
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from julia...done.
(gdb) break ./src/hotspot/cpu/x86/vm_version_x86.cpp:575
No source file named ./src/hotspot/cpu/x86/vm_version_x86.cpp.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (./src/hotspot/cpu/x86/vm_version_x86.cpp:575) pending.
(gdb) run --banner=no
Starting program: /bin/julia --banner=no
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff3365700 (LWP 12483)]
[New Thread 0x7fffe10ba700 (LWP 12489)]
[New Thread 0x7fffe08b9700 (LWP 12490)]
[New Thread 0x7fffde0b8700 (LWP 12491)]
[New Thread 0x7fffdb8b7700 (LWP 12492)]
[New Thread 0x7fffd70b6700 (LWP 12493)]
[New Thread 0x7fffd48b5700 (LWP 12494)]
[New Thread 0x7fffd20b4700 (LWP 12495)]
julia> using JavaCall; JavaCall.init(["-Xmx128m"])

Thread 1 "julia" hit Breakpoint 1, VM_Version::get_processor_features ()
    at ./src/hotspot/cpu/x86/vm_version_x86.cpp:575
575	  get_cpu_info_stub(&_cpuid_info);
(gdb) bt
#0  VM_Version::get_processor_features ()
    at ./src/hotspot/cpu/x86/vm_version_x86.cpp:575
#1  0x00007fffcd1c3b2c in VM_Version::initialize ()
    at ./src/hotspot/cpu/x86/vm_version_x86.cpp:1736
#2  0x00007fffcd1bbfd9 in VM_Version_init ()
    at ./src/hotspot/share/runtime/vm_version.cpp:307
#3  0x00007fffccbd7148 in init_globals ()
    at ./src/hotspot/share/runtime/init.cpp:108
#4  0x00007fffcd141ac7 in Threads::create_vm (args=<optimized out>, 
    canTryAgain=canTryAgain@entry=0x7fffcdbe3fd7)
    at ./src/hotspot/share/runtime/thread.cpp:3733
#5  0x00007fffccc91671 in JNI_CreateJavaVM_inner (args=<optimized out>, 
    penv=0x7fffe6808110, vm=0x7fffe68080b0)
    at ./src/hotspot/share/prims/jni.cpp:3954
#6  JNI_CreateJavaVM (vm=0x7fffe68080b0, penv=0x7fffe6808110, 
    args=<optimized out>) at ./src/hotspot/share/prims/jni.cpp:4045
#7  0x00007fffce38945c in ?? ()
#8  0x0000000000afb0d0 in ?? ()
#9  0x00007fffe75b0b40 in ?? ()
#10 0x0000000000000010 in ?? ()
#11 0x00007ffff76f98ac in jl_thread_self ()
    at /buildworker/worker/package_linux64/build/src/tls.h:15
#12 jl_mutex_wait (safepoint=1, lock=0x7fffcdbe4060)
---Type <return> to continue, or q <return> to quit---
    at /buildworker/worker/package_linux64/build/src/locks.h:23
#13 jl_mutex_lock (lock=0x7fffcdbe4060)
    at /buildworker/worker/package_linux64/build/src/locks.h:93
#14 0x00007ffff76933fc in _jl_invoke (world=2, mfunc=<optimized out>, nargs=1, 
    args=0x7fffe784c950, F=0x7ffff76b0b40 <jl_alloc_array_1d>)
    at /buildworker/worker/package_linux64/build/src/gf.c:2141
#15 jl_apply_generic (F=0x7ffff76b0b40 <jl_alloc_array_1d>, 
    args=0x7fffe784c950, args@entry=0x7fffcdbe4208, nargs=nargs@entry=1)
    at /buildworker/worker/package_linux64/build/src/gf.c:2305
#16 0x00007ffff780c5fe in jl_apply (nargs=2, args=0x7fffcdbe4200)
    at /buildworker/worker/package_linux64/build/src/julia.h:1631
#17 do_call (args=args@entry=0x7fffe7360350, nargs=nargs@entry=2, 
    s=s@entry=0x7fffcdbe4530)
    at /buildworker/worker/package_linux64/build/src/interpreter.c:328
#18 0x00007ffff780c250 in eval_value (e=e@entry=0x7fffe731f690, 
    s=s@entry=0x7fffcdbe4530)
    at /buildworker/worker/package_linux64/build/src/interpreter.c:417
#19 0x00007ffff780cd84 in eval_stmt_value (s=0x7fffcdbe4530, 
    stmt=0x7fffe731f690)
    at /buildworker/worker/package_linux64/build/src/interpreter.c:368
#20 eval_body (stmts=<optimized out>, s=<optimized out>, ip=2, 
    toplevel=<optimized out>)
    at /buildworker/worker/package_linux64/build/src/interpreter.c:778
---Type <return> to continue, or q <return> to quit---
#21 0x00007ffff780d58f in jl_interpret_toplevel_thunk_callback (
    s=0x7fffcdbe4530, vargs=0x7fffcdbe4590)
    at /buildworker/worker/package_linux64/build/src/interpreter.c:888
#22 0x00007ffff76aa8ac in Lenter_interpreter_frame_start_val ()
   from ~/src/julia-1.3.1/bin/../lib/libjulia.so.1
#23 0x00007ffff780df5d in jl_interpret_toplevel_thunk (
    m=m@entry=0x7fffeac78c10 <jl_system_image_data+317776>, 
    src=src@entry=0x7fffe804e390)
    at /buildworker/worker/package_linux64/build/src/interpreter.c:897
#24 0x00007ffff76c7c56 in jl_toplevel_eval_flex (
    m=m@entry=0x7fffeac78c10 <jl_system_image_data+317776>, e=<optimized out>, 
    fast=fast@entry=1, expanded=expanded@entry=0)
    at /buildworker/worker/package_linux64/build/src/toplevel.c:814
#25 0x00007ffff76c777a in jl_toplevel_eval_flex (
    m=m@entry=0x7fffeac78c10 <jl_system_image_data+317776>, e=<optimized out>, 
    fast=fast@entry=1, expanded=expanded@entry=0)
    at /buildworker/worker/package_linux64/build/src/toplevel.c:764
#26 0x00007ffff76c777a in jl_toplevel_eval_flex (
    m=m@entry=0x7fffeac78c10 <jl_system_image_data+317776>, 
    e=e@entry=0x7fffe7d5ab30, fast=fast@entry=1, expanded=expanded@entry=0)
    at /buildworker/worker/package_linux64/build/src/toplevel.c:764
#27 0x00007ffff76c882c in jl_toplevel_eval (
    m=m@entry=0x7fffeac78c10 <jl_system_image_data+317776>, 
---Type <return> to continue, or q <return> to quit---
    v=v@entry=0x7fffe7d5ab30)
    at /buildworker/worker/package_linux64/build/src/toplevel.c:823
#28 0x00007ffff76c88b5 in jl_toplevel_eval_in (
    m=0x7fffeac78c10 <jl_system_image_data+317776>, ex=0x7fffe7d5ab30)
    at /buildworker/worker/package_linux64/build/src/toplevel.c:843
#29 0x00007fffe9eb21a5 in japi1_eval_3749 () at boot.jl:330
#30 0x00007ffff769379c in _jl_invoke (world=26768, mfunc=<optimized out>, 
    nargs=2, args=0x7fffcdbe4a38, 
    F=0x7fffec9b2310 <jl_system_image_data+30961744>)
    at /buildworker/worker/package_linux64/build/src/gf.c:2135
#31 jl_apply_generic (F=0x7fffec9b2310 <jl_system_image_data+30961744>, 
    args=0x7fffcdbe4a38, nargs=<optimized out>)
    at /buildworker/worker/package_linux64/build/src/gf.c:2305
#32 0x00007fffea0abc19 in japi1_eval_user_input_11803 ()
    at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/REPL/src/REPL.jl:86
#33 0x00007fffea0abf18 in macro expansion ()
    at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/REPL/src/REPL.jl:118
#34 japi1_#26_11801 () at task.jl:333
#35 0x00007ffff769379c in _jl_invoke (world=26768, mfunc=<optimized out>, 
    nargs=0, args=0x7fffe80e3390, F=0x7fffe80c4de0)
    at /buildworker/worker/package_linux64/build/src/gf.c:2135
---Type <return> to continue, or q <return> to quit---
#36 jl_apply_generic (F=0x7fffe80c4de0, args=args@entry=0x7fffe80e3390, 
    nargs=nargs@entry=0)
    at /buildworker/worker/package_linux64/build/src/gf.c:2305
#37 0x00007ffff76aee79 in jl_apply (nargs=1, args=0x7fffe80e3388)
    at /buildworker/worker/package_linux64/build/src/julia.h:1631
#38 start_task () at /buildworker/worker/package_linux64/build/src/task.c:659
#39 0x0000000000000000 in ?? ()
(gdb) s
563	void VM_Version::get_processor_features() {
(gdb) s
568	  _features = 0;
(gdb) s
569	  _logical_processors_per_package = 1;
(gdb) s
571	  _L1_data_cache_line_size = 16;
(gdb) s
565	  _cpu = 4; // 486 by default
(gdb) s
566	  _model = 0;
(gdb) s
567	  _stepping = 0;
(gdb) s
568	  _features = 0;
(gdb) s
569	  _logical_processors_per_package = 1;
(gdb) s
571	  _L1_data_cache_line_size = 16;
(gdb) s
575	  get_cpu_info_stub(&_cpuid_info);
(gdb) s

Thread 1 "julia" received signal SIGSEGV, Segmentation fault.
0x00007fffb39e152d in ?? ()
(gdb) continue
Continuing.
[New Thread 0x7fffb380a700 (LWP 12765)]
[New Thread 0x7fffb2a80700 (LWP 12766)]
[New Thread 0x7fffb297e700 (LWP 12767)]
[New Thread 0x7fffa3fff700 (LWP 12768)]
[New Thread 0x7fffa3efd700 (LWP 12769)]
[New Thread 0x7fffa357a700 (LWP 12770)]

Thread 1 "julia" received signal SIGSEGV, Segmentation fault.
0x00007ffff6c72ea3 in printf_positional (s=s@entry=0x7fffcd7edeb0, format=format@entry=0x7fffcd260bd5 "%s%s", readonly_format=readonly_format@entry=0, ap=ap@entry=0x7fffcd7ee078, 
    ap_savep=ap_savep@entry=0x7fffcd7eda58, done=done@entry=0, nspecs_done=0, lead_str_end=0x7fffcd260bd5 "%s%s", work_buffer=0x7fffcd7eda80 "", save_errno=2, 
    grouping=0xffffffffffffffff <error: Cannot access memory at address 0xffffffffffffffff>, thousands_sep=0x0) at vfprintf.c:1708
1708	vfprintf.c: No such file or directory.
(gdb) continue
Continuing.

Thread 1 "julia" received signal SIGSEGV, Segmentation fault.
0x00007ffff6c72ea3 in printf_positional (s=s@entry=0x7fffcd7edeb0, 
    format=format@entry=0x7fffcd260bd5 "%s%s", 
    readonly_format=readonly_format@entry=0, ap=ap@entry=0x7fffcd7ee078, 
    ap_savep=ap_savep@entry=0x7fffcd7eda58, done=done@entry=0, nspecs_done=0, 
    lead_str_end=0x7fffcd260bd5 "%s%s", work_buffer=0x7fffcd7eda80 "", 
    save_errno=2, 
    grouping=0xffffffffffffffff <error: Cannot access memory at address 0xffffffffffffffff>, thousands_sep=0x0) at vfprintf.c:1708
1708	in vfprintf.c
(gdb) continue
Continuing.
Couldn't get registers: No such process.
Couldn't get registers: No such process.
(gdb) [Thread 0x7fffa357a700 (LWP 12770) exited]
[Thread 0x7fffa3efd700 (LWP 12769) exited]
[Thread 0x7fffa3fff700 (LWP 12768) exited]
[Thread 0x7fffb297e700 (LWP 12767) exited]
[Thread 0x7fffb2a80700 (LWP 12766) exited]
[Thread 0x7fffb380a700 (LWP 12765) exited]
[Thread 0x7fffd20b4700 (LWP 12495) exited]
[Thread 0x7fffd48b5700 (LWP 12494) exited]
[Thread 0x7fffd70b6700 (LWP 12493) exited]
[Thread 0x7fffdb8b7700 (LWP 12492) exited]
[Thread 0x7fffde0b8700 (LWP 12491) exited]
[Thread 0x7fffe08b9700 (LWP 12490) exited]
[Thread 0x7fffe10ba700 (LWP 12489) exited]
[Thread 0x7ffff3365700 (LWP 12483) exited]

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.

Segfault of outside process?

Saw this when trying to run the docs

julia> using JavaCall
Loaded /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/server/libjvm.dylib

julia> JavaCall.init(["-Xmx128M"])

signal (11): Segmentation fault: 11
while loading no file, in expression starting on line 0
unknown function (ip: 0x3236792b3)
Allocations: 21886089 (Pool: 21879057; Big: 7032); GC: 45

julia>

info

julia> Base.versioninfo()
Julia Version 0.5.0
Commit 3c9d753* (2016-09-19 18:14 UTC)
Platform Info:
  System: Darwin (x86_64-apple-darwin15.6.0)
  CPU: Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.7.1 (ORCJIT, haswell)

Pkg.test() with Julia-0.5 fails

JavaCall looks for legacy jdk1.6 (on osx) and if the same is not installed the test fails even if JAVA_HOME is set to a valid JDK installation.

julia> ENV["JAVA_HOME"]
"/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home"

julia> Pkg.test("JavaCall")
INFO: Testing JavaCall
Loaded /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/server/libjvm.dylib
Julia Version 0.5.0
Commit 3c9d753 (2016-09-19 18:14 UTC)
Platform Info:
  System: Darwin (x86_64-apple-darwin13.4.0)
  CPU: Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.7.1 (ORCJIT, broadwell)

signal (11): Segmentation fault: 11
while loading /Users/pradeep/.julia/v0.5/JavaCall/test/runtests.jl, in expression starting on line 9
unknown function (ip: 0x3160c42b3)
Allocations: 2693323 (Pool: 2692397; Big: 926); GC: 2
No Java runtime present, requesting install.
====================================================[ ERROR: JavaCall ]====================================================

failed process: Process(`/Applications/Julia-0.5.app/Contents/Resources/julia/bin/julia -Ccore2 -J/Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib --compile=yes --depwarn=yes --check-bounds=yes --code-coverage=none --color=yes --compilecache=yes /Users/pradeep/.julia/v0.5/JavaCall/test/runtests.jl`, ProcessExited(97)) [97]

===========================================================================================================================
ERROR: JavaCall had test errors
 in #test#61(::Bool, ::Function, ::Array{AbstractString,1}) at ./pkg/entry.jl:740
 in (::Base.Pkg.Entry.#kw##test)(::Array{Any,1}, ::Base.Pkg.Entry.#test, ::Array{AbstractString,1}) at ./<missing>:0
 in (::Base.Pkg.Dir.##2#3{Array{Any,1},Base.Pkg.Entry.#test,Tuple{Array{AbstractString,1}}})() at ./pkg/dir.jl:31
 in cd(::Base.Pkg.Dir.##2#3{Array{Any,1},Base.Pkg.Entry.#test,Tuple{Array{AbstractString,1}}}, ::String) at ./file.jl:59
 in #cd#1(::Array{Any,1}, ::Function, ::Function, ::Array{AbstractString,1}, ::Vararg{Array{AbstractString,1},N}) at ./pkg/dir.jl:31
 in (::Base.Pkg.Dir.#kw##cd)(::Array{Any,1}, ::Base.Pkg.Dir.#cd, ::Function, ::Array{AbstractString,1}, ::Vararg{Array{AbstractString,1},N}) at ./<missing>:0
 in #test#3(::Bool, ::Function, ::String, ::Vararg{String,N}) at ./pkg/pkg.jl:258
 in test(::String, ::Vararg{String,N}) at ./pkg/pkg.jl:258

test failure on Java 10: JString methods

Line 172 of runtests.jl is failing on Julia 1.0.0, Java 10.0.2.

method_lists_1: Test Failed at /home/expandingman/.julia/dev/JavaCall/test/runtests.jl:176
  Expression: [getname(typ) for typ = getparametertypes(m)] == ["int"]
   Evaluated: ["java.lang.String", "int"] == ["int"]

So, I'm getting what the tests claim is the correct behavior for Java versions lower than 9.0.0.

My guess is that the tests are probably wrong, and it's ok for later Java versions to return this, and that we should change the test to pass if it's either or.

Does anyone know any more about this?

High-level interface

Not that I expect this issue to be resolved anytime soon, but I thought it would be nice to write down ideas to have something to start with.

In a perfect world I'd like to use JavaCall something like this:

@java foo = new Foo()
@java foo.doStuff("hello").doAnotherStuff()
@java foo.bar

Or even like this:

@java begin
    foo = new Foo()
    foo.doStuff("hello").doAnotherStuff()
    foo.bar
end

A bit closer target may be to implement something like this (i.e. call only one method of one object):

@jcall foo.doStuff("hello")

The problem with such syntax is that it lacks several bits of required information:

jcall(foo, "doStuff", <what return type?>, (<what argument types?>,), "hello")

One way to fix issue with return type is to add them explicitly, similar to Java syntax:

@jcall JString result = foo.doStuff("hello")

Looks quite weird, but may work. However, it's still unclear how to pass argument types. Note, that jcall requires argument types from the method signature which may be parent types of actual arguments, e.g.:

jcall(foo, "doStuff", <what return type?>, (JObject,), "hello")

The best syntax that comes to mind is:

@jcall JString result = foo.doStuff("hello"::JObject)

Or a bit simpler:

@jcall JString obj.doStuff("hello"::JObject)

Another option is to use reflection to infer unknown parameters. Here we have 2 options:

  1. Using macros, generate code that performs reflection during run-time. Easy to implement, but reflection will slow down every call.
  2. Using generated functions, do all the reflection during compile-time and produce pure jcall.

Second option looks attractive, but I have a little experience with generated functions and I'm not sure this will work.

Immediate segfault on OSX, works anyway?

What do you think about this behavior? I have Java installed via Homebrew on OSX

               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: http://docs.julialang.org
   _ _   _| |_  __ _   |  Type "help()" for help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.3.10 (2015-06-24 13:54 UTC)
 _/ |\__'_|_|_|\__'_|  |  Official http://julialang.org/ release
|__/                   |  x86_64-apple-darwin13.4.0

julia> using JavaCall
Loaded /Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Contents/Home/jre/lib/server/libjvm.dylib

julia> JavaCall.init(["-Xmx128M"])

signal (11): Segmentation fault: 11
unknown function (ip: 318931636)

julia> jlm = @jimport java.lang.Math
JavaObject{symbol("java.lang.Math")} (constructor with 2 methods)

julia> jcall(jlm, "sin", jdouble, (jdouble,), pi/2)
1.0

julia> jnu = @jimport java.net.URL
JavaObject{symbol("java.net.URL")} (constructor with 2 methods)

julia> gurl = jnu((JString,), "http://www.google.com")
JavaObject{symbol("java.net.URL")}(Ptr{Void} @0x00007f7ffc199d08)

julia> jcall(gurl, "getHost", JString,())
"www.google.com"

julia> j_u_arrays = @jimport java.util.Arrays
JavaObject{symbol("java.util.Arrays")} (constructor with 2 methods)

julia> jcall(j_u_arrays, "binarySearch", jint, (Array{jint,1}, jint), [10,20,30,40,50,60], 40)
3

Doesn't work in Julia 1.0 yet

julia> using JavaCall
[ Info: Precompiling JavaCall [494afd89-becb-516b-aafa-70d2670c0337]
ERROR: LoadError: LoadError: UndefVarError: start not defined
Stacktrace:
...
in expression starting at C:\Users\tgc\.julia\packages\JavaCall\X7Eto\src\convert.jl:328
in expression starting at C:\Users\tgc\.julia\packages\JavaCall\X7Eto\src\JavaCall.jl:34
ERROR: Failed to precompile JavaCall [494afd89-becb-516b-aafa-70d2670c0337] to C:\Users\tgc\.julia\compiled\v1.0\JavaCall\xsZ3L.ji.

Related to this code comment:
# TODO replace once iterate is available in Compat

How to use different versions of Java?

I have two Java versions on my computer, which is of course 1.8 and 9.
My Java default seems to be 1.8, but is there any way to use other versions?
No problem running the code... just curious! :)

Problem on 64-bit Windows 7

Installation seemed to go fine. Using JavaCall resulted in a "Cannot find java library" error. A manual search showed that jvm.dll is located in "c:\Program Files (x86)\Java\jre7\bin\client". I added the following lines to my .juliarc.jl file:

if !haskey(ENV,"JAVA_LIB")
    ENV["JAVA_LIB"] = "c:\\Program Files (x86)\\Java\\jre7\\bin\\client"
end

and the result is now

julia> using JavaCall
ERROR: Cannot find java library in: {"c:\\Program Files (x86)\\Java\\jre7\\bin\\client"}To override the search, set the JAVA_LIB environment variable to the directory containing jvm.dll
 in error at error.jl:21
 in findjvm at c:\home\simonp\.julia\v0.3\JavaCall\src\JavaCall.jl:77
while loading c:\home\simonp\.julia\v0.3\JavaCall\src\JavaCall.jl, in expression starting on line 80

I then tried loading the dll manually:

julia> dlopen("c:\\Program Files (x86)\\Java\\jre7\\bin\\client\\jvm")
ERROR: could not load module c:\Program Files (x86)\Java\jre7\bin\client\jvm: %1 is not a valid Win32 application.

 in dlopen at c.jl:19

So I think your package's error message could be improved: The DLL was found but it can't be opened. I'm not sure what the dlopen error message is telling me.

Any help would be appreciated.

Thanks,
--Peter

Don't convert Arrays and Strings automatically

Now arrays and strings are automatically converted when passed to and from jcall. This is handful in a number of cases, but consider such an example:

arr = jcall(my_obj, "createVeryBigArray", Array{Int, 1}, ())
jcall(my_other_obj, "doStuffWithBigArray", Void, (Array{Int, 1},), arr)

In this code big array will be first allocated in JVM memory, then copied to Julia memory and converted to Array{Int, 1}, and then copied and converted back to JVM again.

It's not really simple issue, though. For strings it's easy to keep String and JString separate, but arrays don't have corresponding class in Java, so a wrapper or something like that may be needed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.