Integer缓存源码剖析

Posted javatalk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Integer缓存源码剖析相关的知识,希望对你有一定的参考价值。

首先先看一个例题,思考一下下面这段程序会出现什么样的结果,由这道题我们对部分源码进行分析:

        Integer a = 100;
        Integer b = 100;
        Integer c = 130;
        Integer d = 130;
        Integer e = new Integer(100);
        Integer f = new Integer(100);
        System.out.println(a==b);
        System.out.println(c==d);
        System.out.println(e==f);        

看完上面的代码,自己的心里面是不是有了自己的答案,最终的答案是(点击+展开查看答案):

技术图片
true
false
false
View Code

 我们都知道Integer是int的封装类,通常对于基本数据类型直接赋值给封装类就是自动装箱,这样就会为Integer对象分配对内存,对象呢指向不同的地址,Java中==是比较的对象的地址,因此对于c==d为false我们都很确定,其他两对是什么情况呢???

 1  private static class IntegerCache {
 2         static final int low = -128;
 3         static final int high;
 4         static final Integer cache[];
 5 
 6         static {
 7             int h = 127;
 8             String integerCacheHighPropValue =
 9                 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
10             if (integerCacheHighPropValue != null) {
11                 try {
12                     int i = parseInt(integerCacheHighPropValue);
13                     i = Math.max(i, 127);
14                     // Maximum array size is Integer.MAX_VALUE
15                     h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
16                 } catch( NumberFormatException nfe) {
17                     // If the property cannot be parsed into an int, ignore it.
18                 }
19             }
20             high = h;
21 
22             cache = new Integer[(high - low) + 1];
23             int j = low;
24             for(int k = 0; k < cache.length; k++)
25                 cache[k] = new Integer(j++);
26 
27             // range [-128, 127] must be interned (JLS7 5.1.7)
28             assert IntegerCache.high >= 127;
29         }
30 
31         private IntegerCache() {}
32     }

 

IntegerCache是Integer的静态内部类,该类有一个Integer类型的缓存数组,显示默认会缓存[-128,127]之间的数字,默认实例化256个对象(25行),在-128到127之间呢必须被interned(27行),这些是都是静态并且final的,避免重复的实例化和回收,这样做的目的就是为了节省更大的空间,当一个Integer的值在缓存数组之间时,JVM就会直接把该对象在对象池的地址赋值给引用,因此a==b为true就很清楚了。另外,我们还可以在启动JVM时通过更改java.lang.Integer.IntegerCache.high的值来修改缓存的最大值,如果我们把该值修改为了300,那么缓存数组的范围就是[-128,300]

另外对于显式的创建Integer对象,JVM会直接分配新的空间,不会去对象池中检查是否有该对象,对于e==f为false也就很正常了。

下面演示更改缓存的最大值为300:

 首先在run as ——>run Configurations ——>arguments——>VM arguments下配置

-Djava.lang.Integer.IntegerCache.high=300

点击apply,点击run

上面的例题的结果就变为了:

true
true
false

 

以上是关于Integer缓存源码剖析的主要内容,如果未能解决你的问题,请参考以下文章

python---redis缓存页面前戏之剖析render源码

从源码看java中Integer的缓存问题

Spring缓存源码剖析:CacheManager

从JDK源码理解Java Integer的缓存机制

从JDK源码理解Java Integer的缓存机制

MyBatis从入门到精通—源码剖析之二级缓存细节