最近遇到了一个与Java Integer Cache相关的问题,我正在寻找一种禁用它的方法。
现在无法进行测试,因为除非我们使用缓存之外的整数值进行测试,否则无法确定其是否有效。
我们的情况:我们有8个有错误的!=
比较,在测试2个月期间一直正常工作,因为我们从未有一个基础数据库实体的主键大于128。
最近遇到了一个与Java Integer Cache相关的问题,我正在寻找一种禁用它的方法。
现在无法进行测试,因为除非我们使用缓存之外的整数值进行测试,否则无法确定其是否有效。
我们的情况:我们有8个有错误的!=
比较,在测试2个月期间一直正常工作,因为我们从未有一个基础数据库实体的主键大于128。
Integer
的实现细节。如果你使用Integer
,那么你就接受了这个缓存。它是一个好东西,能够减少有效重复对象的数量。Integer.equals
替换它们--这是解决你遇到的问题的正确方法。public static Unsafe getUnsafe() {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
return (Unsafe) theUnsafe.get(null);
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
public static void disableIntegerCache() {
try {
Class<?> clazz = Class.forName("java.lang.Integer$IntegerCache");
Field cache = clazz.getDeclaredField("cache");
Field low = clazz.getDeclaredField("low");
Field high = clazz.getDeclaredField("high");
Unsafe unsafe = getUnsafe();
Object base = unsafe.staticFieldBase(low);
long lowOffset = unsafe.staticFieldOffset(low);
long highOffset = unsafe.staticFieldOffset(high);
long cacheOffset = unsafe.staticFieldOffset(cache);
unsafe.putObjectVolatile(base, cacheOffset, new Integer[0]);
unsafe.putIntVolatile(base, lowOffset, Integer.MAX_VALUE);
unsafe.putIntVolatile(base, highOffset, Integer.MIN_VALUE);
} catch (ClassNotFoundException | NoSuchFieldException | IllegalArgumentException e) {
e.printStackTrace();
}
}
我使用MAX_VALUE和MIN_VALUE是因为在valueOf
方法中与JVM内部机制相关的奇怪行为。
您可以使用Java选项设置缓存大小。以下内容将让您根据需要设置缓存:
-XX:AutoBoxCacheMax=<CACHE_SIZE>
例如:
-XX:AutoBoxCacheMax=1
IntegerCache
中的代码仍将其设置为 [-128, 127]
。此选项只能增加默认值,-XX:AutoBoxCacheMax=1
将不会产生任何影响。 - Karol Dowbecki
new Integer(1);
进行初始化。同时,解雇那个使用!=
进行对象比较的人。 - Kayaman