Вопрос по android – Странно: нельзя изменить значение Integer в jni

4

Я пишу jni-функцию для установки значения двух Java-объектов Integer в C, вот так:

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

В Java я вызвал эту функцию:

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

Выходными данными являются оба «10», почему?

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

Я сделал много тестов и получил следующие очки. (Ответ, комментарии приветствуются)

I don't think this jni native is unable to alter immutable object. After all, the both objects are changed to 10 from 0.

There is some relation to auto-boxing (yes? I'm not sure). Maybe p1 and p2 are specially processed by jvm, made pointed to a single object if initialized with:

Integer p1=0, p2=0;

Если изменить на:

Integer p1=0, p2=1;

или же

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

Результат правильный (р1: 5, р2: 10). Кто-нибудь может уточнить это?

Возможно, то, что я сказал, не правильно. Я написал следующий код в Java:

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

Это выводит 0, 10. Таким образом, они указывают ни на один объект. Я действительно запутался.

Похоже, вы не читали мой комментарий выше. Не делай этого. user207421
и какова величина p2? user370305
Не пытайтесь это сделать. Это нарушит автобокс и кеширование небольших целочисленных значений. user207421
р1 и р2 оба 10 pengguang001
Спасибо! Можете ли вы дать мне больше объяснений по автобоксу по этому вопросу? Если два объекта Integer обновлены, мой код работает. Но я не думаю, что это хороший способ передать такую ценность. pengguang001

Ваш Ответ

2   ответа
2
Integer i1 = 500, i2 = 10000;
testInts(i1, i2);
Log.d("log", "I1 = " + i1); 
Log.d("log", "I2 = " + i2);

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

выход

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

Работает (первый результат на вашем примере). Я вспомнил кое-что, что если значение находится в байтовом (или?) Диапазоне, то Java использует некоторую странную оптимизацию. РЕДАКТИРОВАТЬ: кажется, это правило для автобокс для небольших значений.

код 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;
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededstackoverflow.com/questions/1995113/strangest-language-feature pengguang001
Error: User Rate Limit Exceeded pengguang001
0

целое число изменчиво Вы увидите, что он не имеетset метод.

Error: User Rate Limit Exceeded pengguang001

Похожие вопросы