Skip to content

Commit 880188d

Browse files
authored
Fix JNIVector garbage collection, check if JVM destroyed (#163)
1 parent 96353a4 commit 880188d

File tree

2 files changed

+17
-5
lines changed

2 files changed

+17
-5
lines changed

src/jniarray.jl

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,21 @@ for primitive in [:jboolean, :jchar, :jbyte, :jshort, :jint, :jlong, :jfloat, :j
5050
m = quote
5151
function get_elements!(jarr::JNIVector{$primitive})
5252
sz = Int(JNI.GetArrayLength(jarr.ref.ptr))
53-
jarr.arr = unsafe_wrap(Array, $get_elements(jarr.ref.ptr, Ptr{jboolean}(C_NULL)), sz)
53+
# Free the array in release_elements rather than directly via GC
54+
jarr.arr = unsafe_wrap(Array, $get_elements(jarr.ref.ptr, Ptr{jboolean}(C_NULL)), sz; own = false)
5455
jarr
5556
end
5657
JNIVector{$primitive}(sz::Int) = get_elements!(JNIVector{$primitive}($new_array(sz)))
5758
function release_elements(arg::JNIVector{$primitive})
58-
$release_elements(arg.ref.ptr, pointer(arg.arr), jint(0))
59+
# Make sure that JVM has not been destroyed
60+
if JNI.ppenv[1] != C_NULL
61+
arr = arg.arr
62+
ref = arg.ref
63+
# The correct way would be let ccall handle this by removing typing from JNI wrappers
64+
GC.@preserve arg ref arr begin
65+
$release_elements(ref.ptr, pointer(arr), jint(0))
66+
end
67+
end
5968
arg.arr = nothing
6069
end
6170
function convert_result(::Type{JNIVector{$primitive}}, ptr)

test/runtests.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,6 @@ end
237237
end
238238

239239
@testset "jni_arrays_1" begin
240-
#=
241240
j_u_arrays = @jimport java.util.Arrays
242241
arr = jint[10,20,30,40,50,60]
243242
jniarr = JNIVector(arr)
@@ -252,11 +251,13 @@ end
252251
@test "array" == jcall(buf, "toString", JString, ())
253252

254253
# Ensure JNIVectors are garbage collected properly
255-
for i in 1:100000
254+
# This used to be 1:100000
255+
@info "JNIVector GC test..."
256+
for i in 1:1000
256257
a = JNIVector(jchar[j == i ? 0 : 1 for j in 1:10000])
257258
buf = jcall(JCharBuffer, "wrap", JCharBuffer, (JNIVector{jchar},), a)
258259
end
259-
=#
260+
@info "JNIVector GC test complete."
260261
end
261262

262263
@testset "dates_1" begin
@@ -451,5 +452,7 @@ catch err
451452
sprint(showerror, err, backtrace())
452453
end
453454

455+
# Run GC before we destroy to avoid errors
456+
GC.gc()
454457
# At the end, unload the JVM before exiting
455458
JavaCall.destroy()

0 commit comments

Comments
 (0)