Skip to content

Commit ef31d84

Browse files
committed
fix: two arg jfield, better exception checking
1 parent 0701a5c commit ef31d84

File tree

1 file changed

+56
-64
lines changed

1 file changed

+56
-64
lines changed

src/core.jl

Lines changed: 56 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -260,11 +260,8 @@ const JString = JavaObject{Symbol("java.lang.String")}
260260

261261
function JString(str::AbstractString)
262262
jstring = JNI.NewStringUTF(String(str))
263-
if jstring == C_NULL
264-
geterror()
265-
else
266-
return JString(jstring)
267-
end
263+
checknull(jstring)
264+
return JString(jstring)
268265
end
269266

270267
# jvalue(v::Integer) = int64(v) << (64-8*sizeof(v))
@@ -327,66 +324,59 @@ isarray(juliaclass::String) = endswith(juliaclass, "[]")
327324

328325
function jnew(T::Symbol, argtypes::Tuple = () , args...)
329326
assertroottask_or_goodenv() && assertloaded()
330-
sig = method_signature(Nothing, argtypes...)
331-
jmethodId = JNI.GetMethodID(Ptr(metaclass(T)), String("<init>"), sig)
332-
if jmethodId == C_NULL
333-
throw(JavaCallError("No constructor for $T with signature $sig"))
334-
end
335-
return _jcall(metaclass(T), jmethodId, JavaObject{T}, argtypes, args...; callmethod=JNI.NewObjectA)
327+
jmethodId = checknull(get_method_id(JNI.GetMethodID, Ptr(metaclass(T)), "<init>", Nothing, argtypes))
328+
return _jcall(metaclass(T), jmethodId, JavaObject{T}, argtypes, args...; callmethod=JNI.NewObjectA)
336329
end
337330

338331
_jcallable(typ::Type{JavaObject{T}}) where T = metaclass(T)
339-
_jcallable(obj::JavaObject) = obj
332+
function _jcallable(obj::JavaObject)
333+
isnull(obj) && throw(JavaCallError("Attempt to call method on Java NULL"))
334+
obj
335+
end
340336

341-
# Call static methods
342337
function jcall(ref, method::AbstractString, rettype::Type, argtypes::Tuple = (), args...)
343338
assertroottask_or_goodenv() && assertloaded()
344-
jmethodId = get_method_id(ref, method, rettype, argtypes)
345-
jmethodId==C_NULL && geterror(true)
339+
jmethodId = checknull(get_method_id(ref, method, rettype, argtypes))
346340
_jcall(_jcallable(ref), jmethodId, rettype, argtypes, args...)
347341
end
348342

349-
function get_method_id(typ::Type{JavaObject{T}}, method::AbstractString, rettype::Type, argtypes::Tuple) where T
350-
sig = method_signature(rettype, argtypes...)
351-
JNI.GetStaticMethodID(Ptr(metaclass(T)), String(method), sig)
343+
function jcall(ref, method::JMethod, args...)
344+
assertroottask_or_goodenv() && assertloaded()
345+
jmethodId = checknull(get_method_id(method))
346+
rettype = jimport(getreturntype(method))
347+
argtypes = Tuple(jimport.(getparametertypes(method)))
348+
_jcall(_jcallable(ref), jmethodId, rettype, argtypes, args...)
352349
end
353350

354-
function get_method_id(obj::JavaObject, method::AbstractString, rettype::Type, argtypes::Tuple)
351+
function get_method_id(jnifun, ptr, method::AbstractString, rettype::Type, argtypes::Tuple)
355352
sig = method_signature(rettype, argtypes...)
356-
JNI.GetMethodID(Ptr(metaclass(obj)), String(method), sig)
353+
jnifun(ptr, String(method), sig)
357354
end
358355

359-
function get_method_id(obj::JavaObject, method::JMethod)
360-
sig = method_signature(rettype, argtypes...)
361-
JNI.FromReflectedMethod(method)
356+
function get_method_id(typ::Type{JavaObject{T}}, method::AbstractString, rettype::Type, argtypes::Tuple) where T
357+
get_method_id(JNI.GetStaticMethodID, Ptr(metaclass(T)), method, rettype, argtypes)
362358
end
363359

364-
function jcall(ref, method::JMethod, args...) where T
365-
jmethodId = JNI.FromReflectedMethod(method)
366-
rettype = jimport(getreturntype(method))
367-
argtypes = Tuple(jimport.(getparametertypes(method)))
368-
jmethodId==C_NULL && geterror(true)
369-
_jcall(metaclass(T), jmethodId, rettype, argtypes, args...)
360+
function get_method_id(obj::JavaObject, method::AbstractString, rettype::Type, argtypes::Tuple)
361+
get_method_id(JNI.GetMethodID, Ptr(metaclass(obj)), method, rettype, argtypes)
370362
end
371363

372-
function jcall(obj::JavaObject, method::JMethod, args... )
373-
assertroottask_or_goodenv() && assertloaded()
374-
isnull(obj) && throw(JavaCallError("Attempt to call method on Java NULL"))
375-
jmethodId = JNI.FromReflectedMethod(method)
376-
rettype = jimport(getreturntype(method))
377-
argtypes = Tuple(jimport.(getparametertypes(method)))
378-
jmethodId==C_NULL && geterror(true)
379-
_jcall(obj, jmethodId, rettype, argtypes, args...)
380-
end
364+
get_method_id(method::JMethod) = JNI.FromReflectedMethod(method)
381365

382366
# JMethod invoke
383367
(m::JMethod)(obj, args...) = jcall(obj, m, args...)
384368

385369

386370
function jfield(ref, field, fieldType)
387371
assertroottask_or_goodenv() && assertloaded()
388-
jfieldID = get_field_id(ref, field, fieldType)
389-
jfieldID==C_NULL && geterror(true)
372+
jfieldID = checknull(get_field_id(ref, field, fieldType))
373+
_jfield(_jcallable(ref), jfieldID, fieldType)
374+
end
375+
376+
function jfield(ref, field)
377+
assertroottask_or_goodenv() && assertloaded()
378+
fieldType = jimport(gettype(field))
379+
jfieldID = checknull(get_field_id(ref, field, fieldType))
390380
_jfield(_jcallable(ref), jfieldID, fieldType)
391381
end
392382

@@ -403,8 +393,7 @@ function get_field_id(obj::JavaObject, field::AbstractString, fieldType::Type)
403393
JNI.GetFieldID(Ptr(metaclass(obj)), String(field), signature(fieldType))
404394
end
405395

406-
function get_field_id(obj::JavaObject, field::JField)
407-
fieldType = jimport(gettype(field))
396+
function get_field_id(obj::JavaObject, field::JField, fieldType::Type)
408397
JNI.FromReflectedField(field)
409398
end
410399

@@ -428,7 +417,7 @@ for (x, name) in [(:Type, "Object"),
428417
m = quote
429418
function _jfield(obj::T, jfieldID::Ptr{Nothing}, fieldType::$x) where T <: $t
430419
result = $fieldmethod(Ptr(obj), jfieldID)
431-
result==C_NULL && geterror()
420+
geterror()
432421
return convert_result(fieldType, result)
433422
end
434423
function _jcall(obj::T, jmethodId::Ptr{Nothing}, rettype::$x,
@@ -438,7 +427,7 @@ for (x, name) in [(:Type, "Object"),
438427
result = callmethod(Ptr(obj), jmethodId, Array{JNI.jvalue}(jvalue.(convertedArgs)))
439428
end
440429
cleanup_arg.(convertedArgs)
441-
result==C_NULL && geterror()
430+
geterror()
442431
return convert_result(rettype, result)
443432
end
444433
end
@@ -453,8 +442,7 @@ global const _jmc_cache = [ Dict{Symbol, JavaMetaClass}() ]
453442

454443
function _metaclass(class::Symbol)
455444
jclass=javaclassname(class)
456-
jclassptr = JNI.FindClass(jclass)
457-
jclassptr == C_NULL && throw(JavaCallError("Class Not Found $jclass"))
445+
jclassptr = checknull(JNI.FindClass(jclass))
458446
return JavaMetaClass(class, jclassptr)
459447
end
460448

@@ -474,28 +462,32 @@ javaclassname(class::Symbol) = replace(string(class), "."=>"/")
474462
javaclassname(class::AbstractString) = replace(class, "."=>"/")
475463
javaclassname(::Type{T}) where T <: AbstractVector = JavaCall.signature(T)
476464

477-
function geterror(allow=false)
465+
function checknull(ptr)
466+
if isnull(ptr) && geterror() === nothing
467+
throw(JavaCallError("Null from Java. Not known how"))
468+
end
469+
ptr
470+
end
471+
472+
function geterror()
478473
isexception = JNI.ExceptionCheck()
479474

480475
if isexception == JNI_TRUE
481476
jthrow = JNI.ExceptionOccurred()
482-
jthrow==C_NULL && throw(JavaCallError("Java Exception thrown, but no details could be retrieved from the JVM"))
483-
JNI.ExceptionDescribe() #Print java stackstrace to stdout
484-
JNI.ExceptionClear()
485-
jclass = JNI.FindClass("java/lang/Throwable")
486-
jclass==C_NULL && throw(JavaCallError("Java Exception thrown, but no details could be retrieved from the JVM"))
487-
jmethodId=JNI.GetMethodID(jclass, "toString", "()Ljava/lang/String;")
488-
jmethodId==C_NULL && throw(JavaCallError("Java Exception thrown, but no details could be retrieved from the JVM"))
489-
res = JNI.CallObjectMethodA(jthrow, jmethodId, Int[])
490-
res==C_NULL && throw(JavaCallError("Java Exception thrown, but no details could be retrieved from the JVM"))
491-
msg = unsafe_string(JString(res))
492-
JNI.DeleteLocalRef(jthrow)
493-
throw(JavaCallError(string("Error calling Java: ",msg)))
494-
else
495-
if allow==false
496-
return #No exception pending, legitimate NULL returned from Java
497-
else
498-
throw(JavaCallError("Null from Java. Not known how"))
477+
isnull(jthrow) && throw(JavaCallError("Java Exception thrown, but no details could be retrieved from the JVM"))
478+
try
479+
JNI.ExceptionDescribe() #Print java stackstrace to stdout
480+
jclass = JNI.FindClass("java/lang/Throwable")
481+
isnull(jclass) && throw(JavaCallError("Java Exception thrown, but no details could be retrieved from the JVM"))
482+
jmethodId=JNI.GetMethodID(jclass, "toString", "()Ljava/lang/String;")
483+
isnull(jmethodId) && throw(JavaCallError("Java Exception thrown, but no details could be retrieved from the JVM"))
484+
res = JNI.CallObjectMethodA(jthrow, jmethodId, Int[])
485+
isnull(res) && throw(JavaCallError("Java Exception thrown, but no details could be retrieved from the JVM"))
486+
msg = unsafe_string(JString(res))
487+
throw(JavaCallError(string("Error calling Java: ", msg)))
488+
finally
489+
JNI.ExceptionClear()
490+
JNI.DeleteLocalRef(jthrow)
499491
end
500492
end
501493
end

0 commit comments

Comments
 (0)