1. 程式人生 > >Integer快取原理與JVM調參應用

Integer快取原理與JVM調參應用

基本資料型別的拆箱與裝箱

jvm把一個包裝型別自動轉成基本資料型別叫做拆箱,反之叫做裝箱。例如:


Integer integer = 2 ;//裝箱 實際執行程式碼為Integer integer = Integer.valueOf(2);
int i = integer ;//裝箱 實際執行程式碼為int i = integer.intValue();
</java>

Integer快取原理

程式在執行裝箱操作時,實際執行的程式碼為Integer.valueOf(number);我們檢視這個方法的原始碼,發現number在一定範圍內不建立新的物件,而是直接拿快取。原始碼如下:

     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128
to 127, * inclusive, and may cache other values outside of this range. * * @param i an {@code int} value. * @return an {@code Integer} instance representing {@code i}. * @since 1.5 */ public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return
IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }

low為固定值-128,high可以配置,預設值為127。最高位可以用 AutoBoxCacheMax=XXX來配置。在載入IntegerCache類時,完成對IntegerCache.high的初始化。

 static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");//這裡讀取配置高位
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);//初始化快取

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

事實上,不僅僅Integer有快取機制,其他包裝型別也有快取操作也有快取,只不過只有Integer可以配置上限。

AutoBoxCacheMax引數

-XX:AutoBoxCacheMax這個引數是設定Integer快取上限的引數。理論上講,當系統需要頻繁使用Integer時,或者說堆記憶體中存在大量的Integer物件時,可以考慮提高Integer快取上限,避免JVM重複創造物件,提高記憶體的使用率,減少GC的頻率,從而提高系統的效能。
理論歸理論,這個引數能否提高系統系統關鍵還是要看堆中Integer物件到底有多少、以及Integer的建立的方式。如果堆中的Integer物件很少,重新設定這個引數並不會提高系統的效能。即使堆中存在大量的Integer物件,也要看Integer物件時如何產生的。
1. 大部分Integer物件通過Integer.valueOf()產生。說明程式碼裡存在大量的拆箱與裝箱操作。這時候設定這個引數會系統性能有所提高。
2. 大部分Integer物件通過反射,new產生。這時候Integer物件的產生大部分不會走valueOf()方法,所以設定這個引數也是無濟於事。

如何檢視堆中的物件分佈,需要了解一下JVM的監控工具jmap與jhat,以及物件查詢語言(OQL),這部分內容在下一篇部落格單獨講

## AutoBoxCacheMax與JIT ##