【问题标题】:Set value from JNI in Java : JNI java.lang.NoSuchFieldError从 Java 中的 JNI 设置值:JNI java.lang.NoSuchFieldError
【发布时间】:2014-11-11 19:12:30
【问题描述】:

我正在尝试从 JNI 设置变量的值(java 中的变量)。
我正在使用GetFieldIDSetIntField 来做同样的事情。

以下是我的代码。

ma​​in.c

JNIEXPORT void JNICALL Java_com_example_hello_MainActivity_samplefunc
(JNIEnv *env, jobject obj, jobject x)
{

    jclass class = (*env)->GetObjectClass(env, x);
    jfieldID fid = (*env)->GetFieldID(env, myclass,"a","I");
    (*env)->SetIntField(env, obj ,fid, 10);

    return;
}

MainActivity.java

 package com.example.hello;
 public class MainActivity extends ActionBarActivity 
 {
    int a = -1;

    /* Declaration of Native function &  Load JNI Library*/
    public static native void samplefunc(Class x);
    static {
        System.loadLibrary("hellojni");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Class x = this.getClass();
        Log.d("JNI", "Before : Value of Port: " + a);
        samplefunc(x);
        Log.d("JNI", "After  : Value of Port: " + a);
        return;
    }
 }

预期的 Logcat 输出是:

D/JNI Before : Value of Port: -1
D/JNI After  : Value of Port: 10

但我收到以下错误:

D/JNI     (12607): Before : Value of Port: -1
W/dalvikvm(12607): JNI WARNING: JNI function SetIntField called with exception pending
W/dalvikvm(12607):              in Lcom/example/hello/MainActivity;.samplefunc:(Ljava/lang/Class;)V (SetIntField)
W/dalvikvm(12607): Pending exception is:
I/dalvikvm(12607): java.lang.NoSuchFieldError: no field with name='a' signature='I' in class Ljava/lang/Class;
I/dalvikvm(12607):  at com.example.hello.MainActivity.samplefunc(Native Method)

我想这有点基本,但我是 JNI 的新手。
对此的任何帮助将不胜感激。

我已经看过了: JNI: NoSuchFieldError 但是它没有解释如何设置任何变量的值。

【问题讨论】:

    标签: java android c android-ndk java-native-interface


    【解决方案1】:
    I/dalvikvm(12607): java.lang.NoSuchFieldError: no field with name='a' signature='I' in class Ljava/lang/Class;
    

    这行告诉你它正在寻找一个在Class类而不是你的类MainActivity中带有签名'I'的字段'a'。问题如下:

    // 'x' is of type Class, since you called samplefunc(Class x)
    // Therefore 'class' is set to Class and not MainActivity
    jclass class = (*env)->GetObjectClass(env, x); 
    
    // Here you try to access the field 'a' from class Class and not from your MainActivity. 
    // Hence your error.
    jfieldID fid = (*env)->GetFieldID(env, class,"a","I"); 
    

    编辑:

    一个简单的解决方案是将samplefunc 更改为

    samplefunc(MainActivity x)
    

    然后您可以使用相同的代码并获得 Rolf 建议的正确类 ツ

    【讨论】:

    • 另外需要注意的是:我建议将原生方法更改为 samplefunc(MainActivity x);并且只使用现有的代码。 FindClass 方法只能用于创建新的 Java 对象。
    • 是的,Rolf 关于“myclass”是对的。你确定这个方法只能用于对象创建吗?最近没用过JNI,也许你是对的。将方法更改为 samplefunc(MainActivity x) 可能会更好。
    • 是的,因为在 Java 端创建了多个实例时,JNI 怎么知道要采用哪个类的实例。
    • 啊,你是对的,我想我用静态引用搞砸了。将很快改变这一点
    • @BluesSolo,在使用MainActivity x = new MainActivity(); 并调用samplefunc(x); 我得到JNI WARNING: instance jfieldID 0x6d7aed24 not valid for class Ljava/lang/Class; (SetIntField) W/dalvikvm(13829): in Lcom/example/hello/MainActivity;.samplefunc:(Lcom/example/hello/MainActivity;)V (SetIntField),然后是SIGABRT
    猜你喜欢
    • 2011-09-07
    • 1970-01-01
    • 2012-03-09
    • 1970-01-01
    • 2020-05-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    相关资源
    最近更新 更多