今天在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是不相等的。