4

次のように、C で 2 つの Java Integer オブジェクトの値を設定する jni 関数を作成します。

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 ネイティブが不変オブジェクトを変更できないとは思いません。結局、両方のオブジェクトが 0 から 10 に変更されます。

  2. オートボクシングとの関係があります (はい?よくわかりません)。おそらく、p1 と p2 は jvm によって特別に処理され、次のように初期化された場合、単一のオブジェクトを指すようになります。

    整数 p1=0、p2=0;

次のように変更した場合:

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 を出力します。したがって、それらは単一のオブジェクトを指していません。私は本当に混乱しています。

4

2 に答える 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;
于 2012-05-19T09:26:36.403 に答える
0

整数は変更可能ではないと思います。方法がないことがわかりますset

于 2012-05-18T10:54:55.280 に答える