r17b r16 r13 ndk64 ndk 13b android jni

android - r16 - ndk r13



Extraño: no se puede cambiar el valor de Integer en jni (2)

No creo que Integer sea ​​mutable. Verás que no tiene un método set .

Escribo una función jni para establecer el valor de dos objetos enteros java en C, así:

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

En Java, llamé a esta función:

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);

Los resultados son ambos ''10'', ¿por qué?

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

He hecho muchas pruebas y obtuve los siguientes puntos. (Respuesta, los comentarios son bienvenidos)

  1. No creo que este jni nativo sea incapaz de alterar el objeto inmutable. Después de todo, los dos objetos se cambian a 10 desde 0.

  2. Existe alguna relación con el auto-boxeo (¿sí? No estoy seguro). Tal vez p1 y p2 sean procesados ​​especialmente por jvm, señalados a un solo objeto si se inicializan con:

    Entero p1 = 0, p2 = 0;

Si cambias a:

Integer p1=0, p2=1;

o

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

El resultado es correcto (p1: 5, p2: 10). ¿Alguien puede aclarar esto?

Tal vez lo que dije no es correcto. He escrito el siguiente código en java:

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

Muestra 0, 10. Entonces, apuntan a que no hay un solo objeto. Estoy realmente confundido.


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

o

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

salida

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

Funciona (primer resultado usando tu ejemplo). He recordado algo que dice que si el valor está en el rango de bytes (o?) Entonces Java usa una optimización extraña. EDITAR: aparece que es una regla para el autoboxing para valores pequeños.

código c

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;