【问题标题】:Java valueOf(int) with IntegerCache returns value 3 for valueOf(1)带有 IntegerCache 的 Java valueOf(int) 返回 valueOf(1) 的值 3
【发布时间】:2016-06-06 05:15:26
【问题描述】:

我遇到了 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,值=123

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

内部调用

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

i=1, parameter=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);
}

IntegerCache.low = -128 IntegerCache.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 是最终类型,因此不应有重复值,例如3 在索引 [129] 和 [131]

所以,我最终得到了例外:

java.sql.SQLException: Missing IN or OUT parameter at index:: 1

我的问题是这怎么可能? 请推荐

【问题讨论】:

    标签: java spring jvm ibatis ibatis.net


    【解决方案1】:

    我的问题是这怎么可能?

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

    【讨论】:

      【解决方案2】:

      是的,你是对的。得到了解决方案。 我认为 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 等也存在同样的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-12
        • 2010-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多