JNI loses reference to native methods

Posted by lhw on Stack Overflow See other posts from Stack Overflow or by lhw
Published on 2010-03-16T10:52:08Z Indexed on 2010/03/17 0:51 UTC
Read the original article Hit count: 510

Filed under:
|
|
|

As an example for later use in Android I wrote a simple callback interface. While doing so i ran into the following error or bug or whatever. In C the two commented lines are supposed to be executed resulting in calling the C callback onChange. But instead i get an UnsatisfiedLinkError. Calling the native Method directly in Java works just fine. Calling it directly from C as presented here in the example also produces the UnsatisfiedLinkError. I'm open for any advice concerning this issue or work arounds and so on. The Java Part:

import java.util.LinkedList;
import java.util.Random;

interface Listener {
    public void onChange(float f);
}
class Provider {
    LinkedList<Listener> all;
    public Provider() {
        all = new LinkedList<Listener>();
    }
    public void registerChange(Listener lst) {
        all.add(lst);
    }
    public void sendMsg() {
        Random rnd = new Random();
        for(Listener l : all) {
            try {
                l.onChange(rnd.nextFloat());
            }
            catch(Exception e) {
                System.out.println(e);
            }
        }
    }
}
class Inheritance implements Listener {
    static public void main(String[] args) {
        System.load(System.getProperty("user.dir") + "/libinheritance.so");
    }
    public native void onChange(float f);
}

The C Part:

#include "inheritance.h"

jint JNI_OnLoad(JavaVM *jvm, void *reserved) {
    JNIEnv *env;
    (*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_4); 

    inheritance = (*env)->FindClass(env, "Inheritance");
    o_inheritance = (*env)->NewObject(env, inheritance, (*env)->GetMethodID(env, inheritance, "<init>", "()V"));
    provider = (*env)->FindClass(env, "Provider");
    o_provider = (*env)->NewObject(env, provider, (*env)->GetMethodID(env, provider, "<init>", "()V"));

    (*env)->CallVoidMethod(env, o_inheritance, (*env)->GetMethodID(env, inheritance, "onChange", "(F)V"), 1.0);

    //(*env)->CallVoidMethod(env, o_provider, (*env)->GetMethodID(env, provider, "registerChange", "(LListener;)V"), o_inheritance);
    //(*env)->CallVoidMethod(env, o_provider, (*env)->GetMethodID(env, provider, "sendMsg", "()V"));

    (*env)->DeleteLocalRef(env, o_inheritance);
    (*env)->DeleteLocalRef(env, o_provider);

    return JNI_VERSION_1_4;
}
JNIEXPORT void JNICALL Java_Inheritance_onChange(JNIEnv *env, jobject self, jfloat f) {
    printf("[C] %f\n", f);
}

The header file:

#include <jni.h>
/* Header for class Inheritance */

#ifndef _Included_Inheritance
#define _Included_Inheritance
#ifdef __cplusplus
extern "C" {
#endif

jclass inheritance, provider;
jobject o_inheritance, o_provider;

/*
 * Class:     Inheritance
 * Method:    onChange
 * Signature: (F)V
 */
JNIEXPORT void JNICALL Java_Inheritance_onChange(JNIEnv *, jobject, jfloat);

jint JNI_OnLoad(JavaVM *, void *);

#ifdef __cplusplus
}
#endif
#endif

Compilation:

gcc -c -fPIC -I /usr/lib/jvm/java-6-openjdk/include -I /usr/lib/jvm/java-6-openjdk/include/linux/inheritance.c inheritance.h
gcc -g -o -shared libinheritance.so -shared -Wl,-soname,libinheritance.so -lc inheritance.o

© Stack Overflow or respective owner

Related posts about jni

Related posts about java