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),這部分內容在下一篇部落格單獨講