作为以后在Android中使用的一个例子我写了一个简单的回调接口。虽然这样做我遇到了以下错误或错误或其他什么。在C中,应该执行两个注释行,从而调用C回调onChange。但相反,我得到一个UnsatisfiedLinkError。直接在Java中调用本机方法就可以了。如示例中所示,直接从C调用它也会产生UnsatisfiedLinkError。我愿意接受有关此问题或解决方法的任何建议,等等。 Java部分:
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);
}
C部分:
#include "inheritance.h"
jint JNI_OnLoad(JavaVM *jvm, void *reserved) {
JNIEnv *env;
(*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_4);
jclass inheritance = (*env)->FindClass(env, "Inheritance");
jobject o_inheritance = (*env)->NewObject(env, inheritance, (*env)->GetMethodID(env, inheritance, "<init>", "()V"));
jclass provider = (*env)->FindClass(env, "Provider");
jobject o_provider = (*env)->NewObject(env, provider, (*env)->GetMethodID(env, provider, "<init>", "()V"));
g_inheritance = (*env)->NewGlobalRef(env, inheritance);
g_provider = (*env)->NewGlobalRef(env, provider);
(*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 JNI_OnUnload(JavaVM *jvm, void *reserved) {
JNIEnv *env;
(*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_4);
(*env)->DeleteGlobalRef(env, g_inheritance);
(*env)->DeleteGlobalRef(env, g_provider);
}
JNIEXPORT void JNICALL Java_Inheritance_onChange(JNIEnv *env, jobject self, jfloat f) {
printf("[C] %f\n", f);
}
标题文件:
#include <jni.h>
/* Header for class Inheritance */
#ifndef _Included_Inheritance
#define _Included_Inheritance
#ifdef __cplusplus
extern "C" {
#endif
jclass g_inheritance, g_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
汇编:
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
答案 0 :(得分:2)
阅读GlobalRefs上的JNI规范章节。您不能将jobject或jclass值存储在静态变量中,只能存储在GlobalRefs中。
答案 1 :(得分:1)
仔细考虑之后,如果没有首先注册本机方法,就无法在JNI_onLoad中调用在同一共享对象中实现的本机方法。因为这些是后加载的JNI_onLoad。以下是该问题的解决方案:
inheritance.c
#include "inheritance.h"
jint JNI_OnLoad(JavaVM *jvm, void *reserved) {
JNIEnv *env;
(*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_4);
jclass inheritance = (*env)->FindClass(env, "Inheritance");
(*env)->RegisterNatives(env, inheritance, methods, 1);
jobject o_inheritance = (*env)->NewObject(env, inheritance, (*env)->GetMethodID(env, inheritance, "<init>", "()V"));
jclass provider = (*env)->FindClass(env, "Provider");
jobject o_provider = (*env)->NewObject(env, provider, (*env)->GetMethodID(env, provider, "<init>", "()V"));
(*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"));
return JNI_VERSION_1_4;
}
void onChange(JNIEnv *env, jobject self, jfloat f) {
printf("[C] %f\n", f);
}
inheritance.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Inheritance */
#ifndef _Included_Inheritance
#define _Included_Inheritance
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Inheritance
* Method: onChange
* Signature: (F)V
*/
void onChange(JNIEnv *, jobject, jfloat);
JNINativeMethod methods[] = {
{"onChange", "(F)V", (void *)onChange}
};
jint JNI_OnLoad(JavaVM *, void *);
#ifdef __cplusplus
}
#endif
#endif
inheritance.java
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);
}