面试题答案
一键面试不同JVM版本Integer缓存机制差异及影响
- 缓存范围差异
- OpenJDK 8:默认情况下,Integer类缓存范围是 -128 到 127。即通过
Integer.valueOf(int i)
方法创建Integer对象时,如果i
的值在 -128 到 127 之间,会直接返回缓存中的对象,而不是创建新的对象。例如:
- OpenJDK 8:默认情况下,Integer类缓存范围是 -128 到 127。即通过
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // 输出 true
- **OpenJDK 11**:虽然大部分情况下缓存范围还是 -128 到 127,但在某些特定条件下(如通过`-XX:AutoBoxCacheMax=xxx`参数设置),可以扩大缓存上限。比如设置`-XX:AutoBoxCacheMax=256`,那么在该JVM下:
Integer a = 256;
Integer b = 256;
System.out.println(a == b); // 输出 true
影响:如果程序依赖==
比较两个Integer对象是否相等,并且数值超出默认缓存范围,在不同JVM版本下可能得到不同结果。如果在OpenJDK 8中比较两个大于127的Integer对象,使用==
会返回false,因为会创建新的对象;而在设置了扩大缓存上限的OpenJDK 11中可能返回true。这可能导致程序在不同JVM版本下行为不一致,尤其在一些对对象身份敏感的场景,如在集合中判断元素是否相同。
2. 缓存策略差异
- Oracle JDK 7:在缓存创建上,它是在类加载时就创建好整个缓存数组,即提前初始化好 -128 到 127 范围的Integer对象。
- OpenJDK 14:部分实现中采用了延迟初始化策略,即第一次使用到某个在缓存范围内的值时,才创建对应的缓存对象。
影响:从内存占用角度看,Oracle JDK 7在类加载时就占用了一定内存来存储缓存对象;而OpenJDK 14延迟初始化在一定程度上减少了启动时的内存开销。但如果程序频繁使用不同的缓存范围内的值,OpenJDK 14的延迟初始化可能会带来一定的性能开销,因为每次延迟创建对象都有额外的初始化操作,而Oracle JDK 7由于提前创建好,不存在这种延迟开销。