非常简单的JNI,不知道为什么java.lang.NoSuchFieldError:没有名字的字段

时间:2014-08-03 02:13:02

标签: android java-native-interface

我正在学习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");

它有效,没有错误。

0 个答案:

没有答案