Summary
Java_com_sun_jna_Native_registerMethod creates persistent JNI references before several fallible FFI initialization steps.
Affected code:
|
data->closure_method = (*env)->NewGlobalRef(env, closure_method); |
|
|
|
status = ffi_prep_cif(closure_cif, abi, argc+2, closure_rtype, data->closure_arg_types); |
|
if (ffi_error(env, "Native method mapping", status)) { |
|
goto cleanup; |
|
} |
|
|
|
status = ffi_prep_cif(&data->cif, abi, argc, rtype, data->arg_types); |
|
if (ffi_error(env, "Native method setup", status)) { |
|
goto cleanup; |
|
} |
|
|
|
closure = ffi_closure_alloc(sizeof(ffi_closure), &code); |
|
if (closure == NULL) { |
|
throwByName(env, EUnsupportedOperation, "Failed to allocate closure"); |
|
status = FFI_BAD_ABI; |
|
goto cleanup; |
|
} |
|
status = ffi_prep_closure_loc(closure, closure_cif, dispatch_direct, data, code); |
|
if (status != FFI_OK) { |
|
throwByName(env, EError, "Native method linkage failed"); |
|
goto cleanup; |
|
} |
|
|
|
{ |
|
JNINativeMethod m = { (char*)cname, (char*)sig, code }; |
|
(*env)->RegisterNatives(env, cls, &m, 1); |
|
} |
|
|
|
cleanup: |
|
if (status != FFI_OK) { |
|
free(data->arg_types); |
|
free(data->flags); |
|
free(data); |
|
data = NULL; |
If ffi_prep_cif, ffi_closure_alloc, or ffi_prep_closure_loc fails, execution jumps to cleanup. That path frees data without calling DeleteGlobalRef for data->closure_method.
Because registration did not complete, Native_unregister cannot release this reference later.
Impact
Each failed registration permanently retains the reflected Java Method and potentially its class-loader object graph until JVM shutdown. Repeated failures may cause persistent memory growth.
The same cleanup path also omits some related resources, including weak global references, closure_arg_types, encoding, and an allocated FFI closure.
Suggested fix
Before freeing data on failure:
- Delete
closure_method with DeleteGlobalRef.
- Delete any
from_native and to_native weak global references.
- Free all allocated arrays, encoding data, and FFI closure memory.
Successful registrations should continue to transfer ownership to Native_unregister.
Summary
Java_com_sun_jna_Native_registerMethodcreates persistent JNI references before several fallible FFI initialization steps.Affected code:
jna/native/dispatch.c
Lines 3553 to 3587 in d036ad9
If
ffi_prep_cif,ffi_closure_alloc, orffi_prep_closure_locfails, execution jumps tocleanup. That path freesdatawithout callingDeleteGlobalReffordata->closure_method.Because registration did not complete,
Native_unregistercannot release this reference later.Impact
Each failed registration permanently retains the reflected Java
Methodand potentially its class-loader object graph until JVM shutdown. Repeated failures may cause persistent memory growth.The same cleanup path also omits some related resources, including weak global references,
closure_arg_types,encoding, and an allocated FFI closure.Suggested fix
Before freeing
dataon failure:closure_methodwithDeleteGlobalRef.from_nativeandto_nativeweak global references.Successful registrations should continue to transfer ownership to
Native_unregister.