奇怪:在JNI不能改变Integer的值 [英] Weird: can not change the value of Integer in jni

查看:188
本文介绍了奇怪:在JNI不能改变Integer的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个JNI函数来设置用C两个Java Integer对象的值,就像这样:

  jni_do_something(JNIEnv的* ENV,jobject THIZ,jobject P1,P2 jobject){
    JCLASS℃;
    jfieldID ID;
    C = env->的findClass(爪哇/郎/整型);
    如果(C == NULL)
    {
        LOGD(findClass的失败);
        返回-1;
    }    ID = env-> GetFieldID(三,价值,I);
    如果(ID == NULL)
    {
        LOGD(GetFiledID失败);
        返回-1;
    }    env-> SetIntField(P1,编号,5);
    env-> SetIntField(P2,编号,10);
    返回0;
}

在Java中,我调用此函数:

 本地INT do_something(整数P1,P2的整数);整数P1 = 0,P2 = 0;
do_something(P1,P2);
Log.d(测试,P1+ P1);
Log.d(测试,P2+ P2);

输出均为10,为什么呢?

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

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


  1. 我不认为这JNI本机是无法改变不可变对象。毕竟,无论对象是从0变为10。


  2. 有一定的关系自动装箱(是吗?我不知道)。也许p1和p2是专门由JVM进行处理,制成指向单个对象如果与初始化

    P1整数= 0,P2 = 0;


如果更改为:

 整数P1 = 0,P2 = 1;

 整数P1 =新的整数(0);
整数P2 =新的整数(0);

的结果是正确的(P1:5,P2:10)。任何人都可以澄清这一点?

也许我说的是不是正确的。我用Java编写以下code:

 整数= 0;
整数B = 0;
B = 10;
Log.d(测试,A:+ A);
Log.d(测试,B:+ B);

据输出0,10所以,他们指出,没有一个单一的对象。我真的糊涂了。


解决方案

 整数I1 = 500,I2 = 10000;
testInts(I1,I2);
Log.d(日志,I1 =+ I1);
Log.d(日志,I2 =+ I2);

 整数I1 =新的整数(0),I2 =新的整数(0);
testInts(I1,I2);
Log.d(日志,I1 =+ I1);
Log.d(日志,I2 =+ I2);

输出

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

工程(第一个结果使用您的例子)。我想起了什么,如果值是该字节(或?),那么范围Java使用一些怪异的优化。
编辑:看来它是自动装箱对于小数值的规则

C $ C $ç

  JCLASS clazz所=(* ENV) -  GT; GetObjectClass(ENV,I1);
    jfieldID MI =(* ENV) - GT; GetFieldID(ENV,clazz中,价值,I);    (* ENV) - GT; SetIntField(ENV,I1,MI,5);
    (* ENV) - GT; SetIntField(ENV,I2,MI,10);
    返回0;

I write a jni function to set the value of two java Integer object in C, just 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 are both '10', why?

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

I have done many tests, and got the following points. (Answer, comments are welcome)

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

  2. 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;

If change to:

Integer p1=0, p2=1;

or

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

The result is right (p1:5, p2:10). Can anyone clarify this?

Maybe what I said is not correct. I have write the following code in java:

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

It output 0, 10. So, they point to not a single object. I'm really confused.

解决方案

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

output

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

Works (first result using your example). I have remembered something that if value is in byte (or?) range then java uses some weird optimization. EDIT: appears it 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;

这篇关于奇怪:在JNI不能改变Integer的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆