今天调试程序发现一个诡异的事情,同样的代码,在本地执行和在服务器执行的结果不一样,而参数完全一样,不一样的只是执行环境。后来经过调试发现是类似如下的代码引发的bug:
Integer a = 10000;
Integer b = 10000;
if (a == b) {...}
如上代码,在我本地执行,竟然没有进入if条件内,即a==b
在我本地判断为false了,而在服务器端部署后,服务器判断为ture!
上面的代码明显是一个bug,因为Integer对象做比较的话,-128~127范围内才可以直接用==
判断比较,因为内部做了缓存。但是对于这个范围外的Integer比较,就必须使用equals或者compareTo方法了。这个是大家都知道的事情。所以上面的代码是个bug,但问题是这个bug只在本地调试出现了,而没有在服务器端出现!
开始的时候怀疑是jvm版本的问题,本地jvm是hotspot,而服务器jvm版本是opnjdk。但是在网上没找到相关的说法,感觉jvm标准也不会这么干。后来才搞明白,原来服务器端部署脚本打包jar时添加了如下参数:
-XX:AutoBoxCacheMax=20000
使用Oracle/Sun JDK 6,在server模式下,使用-XX:AutoBoxCacheMax=NNN参数即可将Integer的自动缓存区间设置为[-128,NNN]。注意区间的下界固定在-128不可配置。
在client模式下该参数无效。这个参数是server模式专有的,在c2_globals.hpp中声明,默认值是128;不过这个默认值在默认条件下不起作用,要手动设置它的值或者是开启-XX:+AggressiveOpts参数才起作用。
但个人不建议添加这个编译参数,建议使用Integer的equals或者compareTo方法比较两个Integer,否则即使服务器修改了配置,但这只是减少了bug 出现的概率,而不是从根本上解决了bug。