带有IntegerCache的Java valueOf(int)为valueOf返回值3(1)

时间:2016-02-24 04:28:39

标签: java spring jvm ibatis ibatis.net

我遇到 IntegerCache 的问题: 使用iBatis数据访问框架,内部使用iBatis PreparedStatement类。

调用数据库程序,如

sum(sum(l, []))    #works on lists of lists only.

使用iBatis API设置第一个参数:

{ call UPDATE_PROC(?,?,?,?,?,?)  }
with params : [123, 234, 345, TEST1, 567, TEST2]
  

i = 0,值= 123

这里ps是对PreparedStatement的引用,i是数据库过程中的参数索引。

它内部调用

typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName());
  

i = 1,参数= 123(注意:我是int而不是整数)

使用Java reflection api调用内部调用:

 ps.setInt(i, ((Integer) parameter).intValue());
  

方法:setInt,params:[1,123]

在获取方法调用的i的Integer值时,JVM调用以下方法:

public Object invoke(Object proxy, Method method, Object[] params) throws Throwable
  

IntegerCache.low = -128      IntegerCache.high = 127

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); } 的值以IntegerCache.cache[i + (-IntegerCache.low)]结束,整数缓存索引[129]应该有值IntegerCache.cache[129]但是当我调试代码时,我发现值1 at index [129]:

3

因为IntegerCache是​​最终类型,所以不应该有重复值,例如3指数[129]和[131]

所以,我最终会遇到异常:

, -8, -7, -6, -5, -4, -3, -2, -1, 0, 3 **index[129]**, 2, 3 **index[131]**, 4, 5, 6, 7, 8, 9, 10, 11

我的问题是如何做到这一点? 请建议

2 个答案:

答案 0 :(得分:0)

  

我的问题是如何做到这一点?

某些代码可能会通过反射更改缓存实例的Integer.value字段。

答案 1 :(得分:0)

是的,你是对的。得到了解决方案。 我认为STS JVM调试模式存在问题。当我们更改Integer类型实例的原始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 等相同的问题。