1

I'm trying to set a variable's value (variable in java) from JNI.
I'm using GetFieldID and SetIntField to do the same.

Following is my code.

main.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;
    }
 }

The expected Logcat output is:

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

But i get the following error:

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)

I guess this is a little basic but I'm new to JNI.
Any help on this would be greatly appreciated.

I have already seen this: JNI: NoSuchFieldError however it doesn't explain how a value of any variable is set.

Community
  • 1
  • 1
Saurabh Meshram
  • 8,106
  • 3
  • 23
  • 32

1 Answers1

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

This line tells you that it is looking for a field 'a' with signature 'I' in class Class and not in your class MainActivity. The problem is the following:

// '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"); 

Edit:

An easy solution would be to change the samplefunc to

samplefunc(MainActivity x)

Then you can use the same code and you get the correct class as suggested by Rolf ツ

BluesSolo
  • 608
  • 9
  • 28
  • 1
    Another note to make: I suggest to change the native method to samplefunc(MainActivity x); and just use the existing code. The FindClass method can only be used if you want to create a new Java object. – Rolf ツ Nov 11 '14 at 10:50
  • Yes you are right Rolf about the 'myclass'. Are you sure that this method can be used only for object creating? Haven't used JNI recently, maybe you are right. Changing the method to samplefunc(MainActivity x) may be even better. – BluesSolo Nov 11 '14 at 10:53
  • Yes, because how would JNI know which instance of the class to take when there have been multiple created on the Java side. – Rolf ツ Nov 11 '14 at 10:55
  • Ah you are right, I think I messed it up with static references. Will change this quickly – BluesSolo Nov 11 '14 at 11:01
  • @BluesSolo, on using `MainActivity x = new MainActivity();` and calling `samplefunc(x);` I get `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)` followed by `SIGABRT` – Saurabh Meshram Nov 11 '14 at 12:05
  • Probably because your method is static and your field 'a' is not. You can't set a non-static variable inside a static method. Try to change the field to static or declare the method as non-static and tell me if that worked – BluesSolo Nov 11 '14 at 12:27