才知道,Integer中的缓存范围竟然可以修改

简介: 才知道,Integer中的缓存范围竟然可以修改

前言

我们在java面试中基本都遇到过一个关于Integer缓存的问题,类似下面这样:

public static void main(String[] args) {
    Integer value1 = Integer.valueOf(128);
    Integer value2 = Integer.valueOf(128);
    System.out.println(value1 == value2);
}
复制代码

上述代码中,打印的结果是true还是false?如果把代码改成下面这样呢,结果是否会改变?

public static void main(String[] args) {
    Integer value1 = Integer.valueOf(127);
    Integer value2 = Integer.valueOf(127);
    System.out.println(value1 == value2);
}
复制代码

先把正确答案公布一下,第一段代码结果输出false,第二段代码结果输出true

根本原因

为了搞明白里面的根本原因,我们需要深入源码看一下:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}
复制代码

上面的代码逻辑如下:

1.如果i的范围在IntegerCache.low和IntegerCache.high之间,就从IntegerCache中取值;

2.否则就创建一个新的Integer对象;

再深入查看一下IntegerCache这个类:

private static class IntegerCache {
    // 默认最小值;
    static final int low = -128;
    // 最大值
    static final int high;
    // 数组缓存,用于缓存Integer对象;
    static final Integer cache[];
    static {
        // 默认最大值
        int h = 127;
        // 从虚拟机配置从读取最大值
        String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        // 如果虚拟机中配置了最大值,那么就以虚拟机的最大值优先
        if (integerCacheHighPropValue != null) {
            try {
                // 把最大值转换成int
                int i = parseInt(integerCacheHighPropValue);
                // 如果比127大,就作为最大值;否则127作为最大值
                i = Math.max(i, 127);
                // 计算缓存数组的长度,需要预留129个位置,因为最小值是固定-128,再加上0,所以是129个位置,另外的就是最大值的长度;
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
         }
         // 计算出来的最大值赋值给high
         high = h;
         // 计算出缓存数组的大小,并创建出数组对象
         cache = new Integer[(high - low) + 1];
         // 准备循环填充缓存数组
         int j = low;
         for(int k = 0; k < cache.length; k++)
             cache[k] = new Integer(j++);
         // 断言最大值是否大于等于127;
         assert IntegerCache.high >= 127;
     }
     // 私有构造函数,不允许其他类创建这个IntegerCache,只能再Integer内部使用;
     private IntegerCache() {}
}
复制代码

根据上述源码,也就是说,IntegerCache默认的缓存范围是在[-128,127];只要我们给出的数值范围在[-128,127]内,就会使用到IntegerCache提前创建好的Integer对象,返回的结果全都是true;超出这个范围就只能通过new Integer(i)构建新的对象,返回的结果就是false;

如何修改默认最大值

但是在代码中,我们观察到了最大值是可以从虚拟机的配置参数中获取的,那么是不是意味着我们可以通过修改虚拟机配置参数来修改这个默认最大值呢?答案是可以的!

我们在启动jvm时带上以下参数就可以达到改变缓存范围的目的:

-XX:AutoBoxCacheMax=<size>
复制代码

比如我们指定缓存范围为[-128,256];那么jvm配置参数为:

-XX:AutoBoxCacheMax=256
复制代码

此时,我们第一段代码和第二段代码返回结果都是true,因为只要是在[-128,256]范围内的数值全都从IntegerCache缓存中取值,不会去创建新的对象。

注意:我们设置的最大值不可小于127,否则不生效!

比如我们通过jvm配置参数把最大值设置为100:

-XX:AutoBoxCacheMax=100
复制代码

不好意思,你再去执行前面的两段代码,结果依然是第一段代码输出false,第二段代码输出true。这就说明我们设置的最大值不能比默认的最大值还小。


相关文章
|
7月前
|
存储 缓存 Java
Java中的Integer缓存池
Java中的Integer缓存池
68 0
|
缓存 JSON NoSQL
Map<Integer,Value>放入缓存后取出来变成了Map<String,Value>
Map<Integer,Value>放入缓存后取出来变成了Map<String,Value>
224 0
|
存储 缓存 Java
Java基础:128陷阱之Integer缓存源码研究
Java基础:128陷阱之Integer缓存源码研究
206 0
Java基础:128陷阱之Integer缓存源码研究
|
缓存 Java
包装类详解(装箱(包)、拆箱(包)、Integer类型缓存)
包装类详解(装箱(包)、拆箱(包)、Integer类型缓存)
包装类详解(装箱(包)、拆箱(包)、Integer类型缓存)
|
缓存 资源调度
修改yarn的默认安装和缓存位置
修改yarn的默认安装和缓存位置
666 0
|
Web App开发 编解码 缓存
猿大师播放器在谷歌chrome播放多路海康威视RTSP视频流,修改过缓存后仍然卡顿怎么办?
在用猿大师播放器同时播放多路海康威视的RTSP视频流,2K和4K视频有卡顿情况,修改完缓存和网络配置后仍然卡顿怎么处理?
336 0
猿大师播放器在谷歌chrome播放多路海康威视RTSP视频流,修改过缓存后仍然卡顿怎么办?
|
存储 缓存 Java
Java Integer 缓存特性(Integer最大/小值探究、整型的自动装箱)
Java Integer 缓存特性(Integer最大/小值探究、整型的自动装箱)
299 0
|
缓存
啊哈!C盘又满了?快修改IntelliJ IDEA默认系统缓存cache目录路径
啊哈!C盘又满了?快修改IntelliJ IDEA默认系统缓存cache目录路径
644 0
啊哈!C盘又满了?快修改IntelliJ IDEA默认系统缓存cache目录路径
|
缓存
缓存,究竟是淘汰,还是修改?
允许cache miss的场景,不管是memcache还是redis,当被缓存的内容变化时,是改修改缓存,还是淘汰缓存?这是今天将要讨论的话题。
466 0
|
存储 缓存 Java
JAVA之旅(十七)——StringBuffer的概述,存储,删除,获取,修改,反转,将缓存区的数据存储到数组中,StringBuilder
JAVA之旅(十七)——StringBuffer的概述,存储,删除,获取,修改,反转,将缓存区的数据存储到数组中,StringBuilder 一.StringBuffer概述 关于StringBuffer这个对象,Buffer是什么意思?缓冲区的意思,String一旦初始化时不可以被改变的,而.
2012 0