我正在学习JNI,写了一篇非常简单的JNI。
我想访问Java对象的字段。
我在android 4.4.3 r1源代码上编译。
但是当我在AVD或Nexus 7 2013上运行它时,我得到了同样的错误:
08-02 21:54:06.653: V/SimJni-JNI(1350): [development/cac-practice-android/SimJni/jni/cac_practice_simjni.cpp:15].!@#.enter.
08-02 21:54:06.653: W/dalvikvm(1350): Exception Ljava/lang/NoSuchFieldError; thrown while initializing Lcac/practice/SimJni;
08-02 21:54:06.653: D/AndroidRuntime(1350): Shutting down VM
08-02 21:54:06.663: W/dalvikvm(1350): threadid=1: thread exiting with uncaught exception (group=0xb3a42ba8)
08-02 21:54:06.663: E/AndroidRuntime(1350): FATAL EXCEPTION: main
08-02 21:54:06.663: E/AndroidRuntime(1350): Process: cac.practice, PID: 1350
08-02 21:54:06.663: E/AndroidRuntime(1350): java.lang.NoSuchFieldError: no field with name='mIntField' signature='I' in class Lcac/practice/SimJni;
08-02 21:54:06.663: E/AndroidRuntime(1350): at cac.practice.SimJni.native_init(Native Method)
08-02 21:54:06.663: E/AndroidRuntime(1350): at cac.practice.SimJni.<clinit>(SimJni.java:8)
08-02 21:54:06.663: E/AndroidRuntime(1350): at cac.practice.SimJniActivity.onCreate(SimJniActivity.java:18)
这是我的代码: JNI代码:cac_practice_simjni.cpp
#define LOG_NDEBUG 0
#define LOG_TAG "SimJni-JNI"
#include <utils/Log.h>
#include <assert.h>
#include <jni.h>
#include <JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
using namespace android;
static const char* const kClassSimJni = "cac/practice/SimJni";
static void cac_practice_simjni_native_init(JNIEnv *env)
{
ALOGV("[%s:%d].!@#.enter.",__FILE__,__LINE__);
jclass clazz = env->FindClass("cac/practice/SimJni");
jfieldID intFieldID = env->GetFieldID(clazz, "mIntField", "I");
}
static JNINativeMethod gMethods[] = {
{
"native_init",
"()V",
(void *)cac_practice_simjni_native_init
},
};
int register_cac_practice_simjni(JNIEnv *env)
{
return AndroidRuntime::registerNativeMethods(env, kClassSimJni, gMethods, NELEM(gMethods));
}
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv *env = NULL;
jint result = -1;
if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
ALOGE("[%s:%d].!@#.GetEnv failed.",__FILE__,__LINE__);
goto bail;
}
assert(env != NULL);
if (register_cac_practice_simjni(env) < 0) {
ALOGE("[%s:%d].!@#.SimJni native registration failed.",__FILE__,__LINE__);
goto bail;
}
// success, return valid version number
result = JNI_VERSION_1_4;
bail:
return result;
}
SimJni.java:
package cac.practice;
import android.util.Log;
public class SimJni {
static {
System.loadLibrary("simjni_jni");
native_init();
}
private static final String TAG = "SimJni";
private int mIntField;
private static native void native_init();
}
在SimJniActivty.java的OnCreate()中,我写道:
SimJni mSimJni = new SimJni();
mIntField 是SimJni.java的整数字段, 所以我不知道
的错误jfieldID intFieldID = env-&gt; GetFieldID(clazz,&#34; mIntField &#34;,&#34; 我&#34;);在cac_practice_simjni.cpp
中jclass clazz = env->FindClass(kClassSimJni);
if (clazz == NULL) {
ALOGE("[%s:%d].!@#.clazz == NULL.",__FILE__,__LINE__);
}
if (intFieldID == 0) {
ALOGV("[%s:%d].!@#.call GetFieldID().",__FILE__,__LINE__);
intFieldID = env->GetFieldID(clazz, "mIntField", "I");
}
我检查了FindClass()的返回值,它不是null。
我修改了代码以尝试其他Java类:
jclass clazz = env->FindClass("android/media/MediaScanner");
intFieldID = env->GetFieldID(clazz, "mNativeContext", "I");
然后传递,没有错误。
我认为代码是正确的:
intFieldID = env->GetFieldID(clazz, "mIntField", "I");
SimJni.java实际上有一个名为&#34; mIntField&#34;的整数字段。
我认为问题是JNI无法识别&#34; cac.practice.SimJni&#34;的内容。 我把SimJni.java放在apk源代码路径下:SimJni / src / cac / practive /.
是否有任何路径设置应添加到Android.mk(用于构建libsimjni_jni.so)? 然后JNI可以识别cac.practice.SimJni以及android.media.MediaScanner。
2014年8月6日
我做了另一个测试:
我把SimJni.java移到了 机器人/框架/碱/媒体/ JAVA /机器人/媒体/ 并将包修改为android.media, 然后我重新编译framework.jar和framework2.jar。
所以SimJni.java包含在framework.jar / framework2.jar中。
将jni代码修改为:
jclass clazz = env->FindClass("android/media/SimJni");
intFieldID = env->GetFieldID(clazz, "mIntField", "I");
它有效,没有错误。