`

Integer源码浅析IntegerCache

 
阅读更多
一、引例,看如下代码
		int a = 100, b = 100;
		System.out.println(a == b); // true,缓存了
		Integer c = 1000, d = 1000;
		System.out.println(c == d); // false,没有缓存,要new
		Integer e = -128, f = -128;
		System.out.println(e == f); // true,缓存了
		Integer g = -129, h = -129;
		System.out.println(g == h); // false,没有缓存,要new


二、究竟哪个范围的整型数被缓存而不需要new了呢?先了解一下什么是“自动装箱池”,再围观IntegerCache源码就清楚。

1、看API里面的注释
    /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage. During VM initialization the
     * getAndRemoveCacheProperties method may be used to get and remove any system
     * properites that configure the cache size. At this time, the size of the
     * cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>.
     */
getAndRemoveCacheProperties方法,用于获取或移除JDK对Integer设置的缓存属性,同时也是调整jvm:AutoBoxCacheMax选项,调整“自动装箱池”的大小
  // value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
    private static String integerCacheHighPropValue; 

    static void getAndRemoveCacheProperties() {
        if (!sun.misc.VM.isBooted()) {
            Properties props = System.getProperties();
            integerCacheHighPropValue =
                (String)props.remove("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null)
                System.setProperties(props);  // remove from system props
        }
    }


2、IntegerCache源码
    // IntegerCache,一个内部类,注意它的属性都是定义为static final
    private static class IntegerCache {
        static final int high; //缓存上界,暂为null
        static final Integer cache[]; //缓存的整型数组
        
        // 块,为什么定义为块
        static {
            final int low = -128; // 缓存下界,不可变了。只有上界可以改变

            // high value may be configured by property
            // h值,可以通过设置jdk的AutoBoxCacheMax参数调整(以下有解释),自动缓存区间设置为[-128,N]。注意区间的下界是固定
            int h = 127;
            
            if (integerCacheHighPropValue != null) {
                // Use Long.decode here to avoid invoking methods that
                // require Integer's autoboxing cache to be initialized
                // 通过解码integerCacheHighPropValue,而得到一个候选的上界值
                int i = Long.decode(integerCacheHighPropValue).intValue();
                // 取较大的作为上界,但又不能大于Integer的边界MAX_VALUE
                i = Math.max(i, 127);     
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - -low);
            }
            high = h; //上界确定
            // 就可以创建缓存块,注意缓存数组大小
            cache = new Integer[(high - low) + 1]; //
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++); // -128到high值逐一分配到缓存数组
        }

        private IntegerCache() {}
    }



看API里面的注释
    /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage. During VM initialization the
     * getAndRemoveCacheProperties method may be used to get and remove any system
     * properites that configure the cache size. At this time, the size of the
     * cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>.
     */
getAndRemoveCacheProperties方法,用于获取或移除JDK对Integer设置的缓存属性,同时也是调整jvm:AutoBoxCacheMax选项,调整“自动装箱池”的大小
  // value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
    private static String integerCacheHighPropValue; 

    static void getAndRemoveCacheProperties() {
        if (!sun.misc.VM.isBooted()) {
            Properties props = System.getProperties();
            integerCacheHighPropValue =
                (String)props.remove("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null)
                System.setProperties(props);  // remove from system props
        }
    }


-------------------以下为补充内容------------------

最近在看Long类,顺便贴个LongCache来比较,相对Integer简单很多,就像ByteCache一样。
 private static class LongCache {
	private LongCache(){}
        // 可见下界和上界就固定了,-128到127
	static final Long cache[] = new Long[-(-128) + 127 + 1];

	static {
	    for(int i = 0; i < cache.length; i++)
		cache[i] = new Long(i - 128);
	}
    }

 public static Long valueOf(long l) {
	final int offset = 128;
	if (l >= -128 && l <= 127) { // will cache
	    return LongCache.cache[(int)l + offset];
	}
        return new Long(l);
    }

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics