使用IntegerCache的Java valueOf(int)方法对于valueOf(1)返回值为3。

4
我遇到了“IntegerCache”的问题: 我正在使用iBatis数据访问框架,该框架内部使用iBatis PreparedStatement类。
调用数据库存储过程如下:
{ call UPDATE_PROC(?,?,?,?,?,?)  }
with params : [123, 234, 345, TEST1, 567, TEST2]

当使用iBatis API设置第一个参数时,应该使用“:”。
typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName());

i=0,value=123
这里的ps是对PreparedStatement的引用,i是数据库过程中的参数索引。
它内部调用了:
 ps.setInt(i, ((Integer) parameter).intValue());

i=1,参数=123(注意:i是int类型,不是Integer)
在Java反射API中进行了内部调用:
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable

方法: setInt,参数:[1, 123]
在调用方法时获取i的整数值,JVM调用以下方法:
public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

整数缓存.low = -128 整数缓存.high = 127
当调用IntegerCache.cache [i +(- IntegerCache.low)]时,它的值最终为IntegerCache.cache [129]。 在整数缓存索引[129]处应该有值1,但是当我调试代码时,发现在索引[129]处的值为3:
, -8, -7, -6, -5, -4, -3, -2, -1, 0, 3 **index[129]**, 2, 3 **index[131]**, 4, 5, 6, 7, 8, 9, 10, 11

"由于IntegerCache是最终类型,不应该有重复的值,例如在索引[129]和[131]处出现了3。因此,我最终遇到了异常:"
java.sql.SQLException: Missing IN or OUT parameter at index:: 1

我的问题是这怎么可能实现?请提建议。
2个回答

0
我的问题是这怎么可能实现呢?
一些代码可能会通过反射来更改缓存实例的Integer.value字段。

0

是的,你说得对。已经找到了解决方案。

我认为STS JVM调试模式存在问题。当我们更改整数类型的原始int属性值时,它会覆盖IntegerCache的值。

这不应该发生,因为下一次请求相同的值时,它会返回被覆盖的值。

使用以下代码进行了小型POC测试,可以在正常模式和调试模式下重现此问题:

public class TestEclipseJVMDebugger {

    public static void main(String[] argc) {

        Integer i1 = new Integer(27);
        int i2 = 7;

        assert (-128 <= i1 && i1 <= 127);
        assert (-128 <= i2 && i2 <= 127);

        System.out.println("i1 = " + i1);
        i1 = Integer.valueOf(i2);
        System.out.println("i1 = " + i1);

        System.out
                .println("apply debug point here and change value of primitive data type of i1 to 666 from debug mode");
        System.out.println("i1 = " + i1);
        i1 = Integer.valueOf(i2);
        System.out.println("i1 = " + i1);

    }

}

我不知道为什么Eclipse JVM调试模式允许直接更新原始数据类型的值,因为它们会直接覆盖核心JVM类的引用值。

然后我认为StringCache,DoubleCache等也存在同样的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接