Weird: cannot change Integer value in jni

I am writing a jni function to set the value of two Java Integer objects in C, like this:

jni_do_something(JNIEnv *env, jobject thiz, jobject p1, jobject p2) { jclass c; jfieldID id; c = env->FindClass("java/lang/Integer"); if (c==NULL) { LOGD("FindClass failed"); return -1; } id = env->GetFieldID(c, "value", "I"); if (id==NULL) { LOGD("GetFiledID failed"); return -1; } env->SetIntField(p1, id, 5); env->SetIntField(p2, id, 10); return 0; } 

In java, I called this function:

 native int do_something(Integer p1, Integer p2); Integer p1=0, p2=0; do_something(p1, p2); Log.d("test", "p1: "+p1); Log.d("test", "p2: "+p2); 

The output is "10", why?

=================================================

I did a lot of tests and got the following points. (Reply, comments are welcome)

  • I do not think that this jni native cannot change an immutable object. In the end, both objects are changed to 10 out of 0.

  • There is something to do with auto-boxing (yes? I'm not sure). Perhaps p1 and p2 are specially processed by jvm, it points to the same object if it is initialized:

    The integer p1 = 0, p2 = 0;

If you change to:

 Integer p1=0, p2=1; 

or

 Integer p1 = new Integer(0); Integer p2 = new Integer(0); 

The result is correct (p1: 5, p2: 10). Can this explain this?

Perhaps what I said is wrong. I wrote the following code in java:

 Integer a = 0; Integer b = 0; b = 10; Log.d("test", "a: "+a); Log.d("test", "b: "+b); 

It prints 0, 10. Thus, they point to more than one object. I'm really confused.

+4
source share
2 answers
 Integer i1 = 500, i2 = 10000; testInts(i1, i2); Log.d("log", "I1 = " + i1); Log.d("log", "I2 = " + i2); 

or

 Integer i1 = new Integer(0), i2 = new Integer(0); testInts(i1, i2); Log.d("log", "I1 = " + i1); Log.d("log", "I2 = " + i2); 

conclusion

 I1 = 10 I2 = 10 I1 = 5 I2 = 10 I1 = 5 I2 = 10 

Works (first result using your example). I remembered something that if the value is in bytes (or?), Then java uses some weird optimization. EDIT: It seems like this is a rule for autoboxing for small values.

c code

  jclass clazz = (*env)->GetObjectClass(env, i1); jfieldID mi = (*env)->GetFieldID(env, clazz, "value", "I"); (*env)->SetIntField(env, i1, mi, 5); (*env)->SetIntField(env, i2, mi, 10); return 0; 
+1
source

I do not think Integer is changed. You will see that it does not have a set method.

0
source

Source: https://habr.com/ru/post/1413133/


All Articles