Version of JNA and related jars
all version
Version and vendor of the java virtual machine
all
Operating system
all
System architecture (CPU type, bitness of the JVM)
Complete description of the problem
The number of arg_classes created by create_callback and the number of arg_classes released by create_callback are inconsistent.
for (i=0;i < argc;i++) {
int jtype;
jclass cls = (*env)->GetObjectArrayElement(env, arg_classes, i);
if ((cb->conversion_flags[i] = get_conversion_flag(env, cls)) != CVT_DEFAULT) {
cb->arg_classes[i] = (*env)->NewWeakGlobalRef(env, cls);
cvt = 1;
}
else {
cb->arg_classes[i] = NULL;
}
...
}
When direct is false , free the cb->arg_classes , but not free JNI weak reference.
https://github.com/java-native-access/jna/blob/master/native/callback.c#L219C3-L224
if (!direct || !cvt) {
free(cb->conversion_flags);
cb->conversion_flags = NULL;
free(cb->arg_classes);
cb->arg_classes = NULL;
}
void
free_callback(JNIEnv* env, callback *cb) {
(*env)->DeleteWeakGlobalRef(env, cb->object);
ffi_closure_free(cb->closure);
free(cb->arg_types);
if (cb->arg_classes) {
unsigned i;
for (i=0;i < cb->cif.nargs;i++) {
if (cb->arg_classes[i]) {
(*env)->DeleteWeakGlobalRef(env, cb->arg_classes[i]);
}
}
free(cb->arg_classes);
}
...
}
Steps to reproduce
native code
#include <stdio.h>
typedef void(*callback_function)(int, void *);
void set_callback(callback_function callback) {
// Call Java callback function with parameter 42
callback(42, NULL);
}
gcc -shared -fPIC -o libjnatest.so jna_test.c
java code
package com.sun.jna;
public interface MyCallback extends Callback {
void callback(int id, Pointer pointer);
}
package com.sun.jna;
public class MyCallbackImpl implements MyCallback {
@Override
public void callback(int id, Pointer pointer) {
// System.out.println(pointer);
}
}
package com.sun.jna;
public class Example {
// static MyCallback myCallback = new MyCallbackImpl();
public interface MyLibrary extends Library {
MyLibrary INSTANCE = Native.loadLibrary(System.getProperty("user.dir") + "/libjnatest.so", MyLibrary.class);
void set_callback(Callback myCallback);
}
public static void main(String[] args) throws InterruptedException {
System.out.println();
System.out.println("--------------------start--------------------");
test(1000000);
System.out.println("--------------------end--------------------");
Thread.sleep(1000000L);
}
static void test(int loop) {
for (int i = 0; i < loop; i++) {
MyCallback myCallback = new MyCallbackImpl();
MyLibrary.INSTANCE.set_callback(myCallback);
CallbackReference callbackReference = CallbackReference.callbackMap.get(myCallback);
// free reference
callbackReference.dispose();
}
}
}
Version of JNA and related jars
all version
Version and vendor of the java virtual machine
all
Operating system
all
System architecture (CPU type, bitness of the JVM)
Complete description of the problem
The number of arg_classes created by create_callback and the number of arg_classes released by create_callback are inconsistent.
create_callback uses
argcas the number ofarg_classes. When(cb->conversion_flags[i] = get_conversion_flag(env, cls)) != CVT_DEFAULTis true, invoke NewWeakGlobalRef.https://github.com/java-native-access/jna/blob/master/native/callback.c#L154-L163
When
directis false , free thecb->arg_classes, but not free JNI weak reference.https://github.com/java-native-access/jna/blob/master/native/callback.c#L219C3-L224
free_callback uses
cb->cif.nargsas the number of arg_classes that need to be released, direct is false, cb->arg_classes is NULL. This results in the JNI weak global reference of arg_classes not being released.https://github.com/java-native-access/jna/blob/master/native/callback.c#L329C2-L335C1
Steps to reproduce
native code
java code