奇怪:无法在jni中更改Integer的值

时间:2012-05-18 09:41:10

标签: android java-native-interface

我编写了一个jni函数来设置C中两个java Integer对象的值,就像这样:

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',为什么?

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

我做了很多测试,得到了以下几点。 (答案,欢迎评论)

  1. 我不认为这个jni native不能改变不可变对象。毕竟,两个对象从0更改为10.

  2. 与自动拳击有一些关系(是的?我不确定)。也许p1和p2是由jvm专门处理的,如果使用:

    初始化则指向单个对象

    整数p1 = 0,p2 = 0;

  3. 如果改为:

    Integer p1=0, p2=1;
    

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

    结果是对的(p1:5,p2:10)。任何人都可以澄清这个吗?

    也许我所说的不正确。我在java中编写了以下代码:

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

    输出0,10。因此,它们指向的不是单个对象。我真的很困惑。

2 个答案:

答案 0 :(得分: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

Works(使用您的示例的第一个结果)。我记得如果值在字节(或?)范围内,那么java会使用一些奇怪的优化。 编辑:似乎是小值自动装箱的规则。

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 :(得分:0)

我认为Integer不可变。你会发现它没有set方法。