今天在javaeye上看到一兄弟贴的代码,
1: int a = 1000, b = 1000; 2: System.out.println(a == b); 3: Integer c = 1000, d = 1000; 4: System.out.println(c == d); 5: Integer e = 100,h = 100; 6: System.out.println(e == h);
运行程序后,输出的结果是:true false true, 看到这个结果,我是百思不得其解,第三行跟第五行明明初始化的一样,为什么结果不一样呢,于是找答案
原来根据java语言规范,符合规范的Java实现必须保证Integer的缓存至少要覆盖[-128, 127]的范围。
使用Oracle/Sun JDK 6,在server模式下,使用-XX:AutoBoxCacheMax=NNN参数即可将Integer的自动缓存区间设置为[-128,NNN]。注意区间的下界固定在-128不可配置。
在client模式下该参数无效。这个参数是server模式专有的,在c2_globals.hpp中声明,默认值是128;不过这个默认值在默认条件下不起作用,要手动设置它的值或者是开启-XX:+AggressiveOpts参数才起作用。
在设置了-XX:+AggressiveOpts启动参数后,AutoBoxCacheMax的默认值会被修改为20000并且生效
从这里,也就是说在sun jdk的server模式中可以通过设置-XX:AutoBoxCacheMax这个参数来确定Integer自动缓存的大小,然后在client模式中这个参数是不支持的,但是可以通过启用-XX:+AggressiveOpts这个参数来调整Integer的自动缓存大小,可调整到20000,请看下面JVM实现代码:
// Aggressive optimization flags -XX:+AggressiveOpts void Arguments::set_aggressive_opts_flags() { #ifdef COMPILER2 if (AggressiveOpts || !FLAG_IS_DEFAULT(AutoBoxCacheMax)) { if (FLAG_IS_DEFAULT(EliminateAutoBox)) { FLAG_SET_DEFAULT(EliminateAutoBox, true); } if (FLAG_IS_DEFAULT(AutoBoxCacheMax)) { FLAG_SET_DEFAULT(AutoBoxCacheMax, 20000); } // Feed the cache size setting into the JDK char buffer[1024]; sprintf(buffer, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax); add_property(buffer); } // ... #endif }
然后再回到代码本身,Integer e = 100,h = 100; 这里编译器会自动帮我们进行box操作,所谓自动装箱即会调用Integer.valueOf(int)方法,
同时这个值100有事在缓存区域内,所以会直接读取缓存的内容;不过Integer c = 1000, d = 1000; 1000是大于Integer的默认缓存范围的,所以c d是不相等的。
同时也可以测试:Integer e = 100 ,f = Integer.valueOf(100), 可以发现 e == f也会打印true,
但是 Integer h = 100, g = new Integer(100); g是新建了一个Integer对象, 所以h g是不相等的。