a == b (10): true
a == c (10): true
127 == : true
128 == : true
128 equals : true
-128 == : true
-129 == : false
new(10) == valueOf(10): false
1000 == : true
对照结论:
表达式
默认
AutoBoxCacheMax=1000
原因
10 / 127 / -128 的 ==
true
true
落在默认 [low, high]=[-128, 127]
128 / 1000 的 ==
false
true
默认超出 high;抬高后命中缓存
-129 的 ==
false
false
low 写死为 -128,下界抬不了
new Integer(10) == valueOf(10)
false
false
构造器总是新对象
128 的 equals
true
true
equals 比值,不依赖缓存
IntegerCache 类注释
valueOf(int) 上方、IntegerCache 定义前的注释:
java
1/**
2 * Cache to support the object identity semantics of autoboxing for values between
3 * -128 and 127 (inclusive) as required by JLS.
4 *
5 * The cache is initialized on first usage. The size of the cache
6 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
7 * During VM initialization, java.lang.Integer.IntegerCache.high property
8 * may be set and saved in the private system properties in the
9 * jdk.internal.misc.VM class.
10 *
11 * WARNING: The cache is archived with CDS and reloaded from the shared
12 * archive at runtime. The archived cache (Integer[]) and Integer objects
13 * reside in the closed archive heap regions. Care should be taken when
14 * changing the implementation and the cache array should not be assigned
15 * with new Integer object(s) after initialization.
16 */
/**
* 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. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* jdk.internal.misc.VM class.
*
* WARNING: The cache is archived with CDS and reloaded from the shared
* archive at runtime. The archived cache (Integer[]) and Integer objects
* reside in the closed archive heap regions. Care should be taken when
* changing the implementation and the cache array should not be assigned
* with new Integer object(s) after initialization.
*/
拆开看:
要点
含义
JLS
[-128, 127] 装箱必须具备对象同一性
首次使用初始化
静态块在类首次用到时执行
-XX:AutoBoxCacheMax
可抬高缓存上界
IntegerCache.high 属性
VM 初始化时写入 jdk.internal.misc.VM 的私有系统属性
CDS WARNING
缓存可随 CDS 归档;初始化后不要再往数组里塞新的 Integer
静态块末尾还有断言注释:range [-128, 127] must be interned (JLS7 5.1.7)。
IntegerCache 静态初始化
java
1privatestaticclassIntegerCache{ 2staticfinalintlow=-128; 3staticfinalinthigh; 4staticfinalInteger[]cache; 5staticInteger[]archivedCache; 6 7static{ 8// high value may be configured by property 9inth=127;10StringintegerCacheHighPropValue=11VM.getSavedProperty("java.lang.Integer.IntegerCache.high");12if(integerCacheHighPropValue!=null){13try{14h=Math.max(parseInt(integerCacheHighPropValue),127);15// Maximum array size is Integer.MAX_VALUE16h=Math.min(h,Integer.MAX_VALUE-(-low)-1);17}catch(NumberFormatExceptionnfe){18// If the property cannot be parsed into an int, ignore it.19}20}21high=h;2223// Load IntegerCache.archivedCache from archive, if possible24CDS.initializeFromArchive(IntegerCache.class);25intsize=(high-low)+1;2627// Use the archived cache if it exists and is large enough28if(archivedCache==null||size>archivedCache.length){29Integer[]c=newInteger[size];30intj=low;31for(inti=0;i<c.length;i++){32c[i]=newInteger(j++);33}34archivedCache=c;35}36cache=archivedCache;37// range [-128, 127] must be interned (JLS7 5.1.7)38assertIntegerCache.high>=127;39}4041privateIntegerCache(){}42}
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer[] cache;
static Integer[] archivedCache;
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
h = Math.max(parseInt(integerCacheHighPropValue), 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
// Load IntegerCache.archivedCache from archive, if possible
CDS.initializeFromArchive(IntegerCache.class);
int size = (high - low) + 1;
// Use the archived cache if it exists and is large enough
if (archivedCache == null || size > archivedCache.length) {
Integer[] c = new Integer[size];
int j = low;
for(int i = 0; i < c.length; i++) {
c[i] = new Integer(j++);
}
archivedCache = c;
}
cache = archivedCache;
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
循环里是 c[i] = new Integer(j++)。 这里是构建缓存本身,不能再调 valueOf,否则会在 IntegerCache 尚未就绪时回头依赖缓存。
同文件里 parseInt 也有类似警告:
java
1/*
2 * WARNING: This method may be invoked early during VM initialization
3 * before IntegerCache is initialized. Care must be taken to not use
4 * the valueOf method.
5 */
/*
* WARNING: This method may be invoked early during VM initialization
* before IntegerCache is initialized. Care must be taken to not use
* the valueOf method.
*/
VM 极早阶段只能用基本类型路径,不能碰依赖缓存的 valueOf。
valueOf(int)
java
1/**
2 * Returns an {@code Integer} instance representing the specified
3 * {@code int} value. If a new {@code Integer} instance is not
4 * required, this method should generally be used in preference to
5 * the constructor {@link #Integer(int)}, as this method is likely
6 * to yield significantly better space and time performance by
7 * caching frequently requested values.
8 *
9 * This method will always cache values in the range -128 to 127,
10 * inclusive, and may cache other values outside of this range.
11 *
12 * @param i an {@code int} value.
13 * @return an {@code Integer} instance representing {@code i}.
14 * @since 1.5
15 */16@IntrinsicCandidate17publicstaticIntegervalueOf(inti){18if(i>=IntegerCache.low&&i<=IntegerCache.high)19returnIntegerCache.cache[i+(-IntegerCache.low)];20returnnewInteger(i);21}
/**
* 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
*/
@IntrinsicCandidate
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
命中与未命中
条件
行为
low <= i <= high
返回 cache[i - low](写法是 i + (-low))
否则
new Integer(i),每次新对象
默认 low = -128 时下标:
值
下标
-128
0
0
128
127
255
128
超出,走 new
文档句 always cache [-128, 127],may cache other values 与 high 可配置完全一致。
indicates that an annotated method may be (but is not guaranteed to be) intrinsified by the HotSpot VM. A method is intrinsified if the HotSpot VM replaces the annotated method with hand-written assembly and/or hand-written compiler IR