Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
禁用Java整数缓存_Java - Fatal编程技术网

禁用Java整数缓存

禁用Java整数缓存,java,Java,最近偶然发现了一个与Java整数缓存相关的问题,我正在寻找一种禁用它的方法 现在测试是不可能的,因为我们不能说它有效,除非我们在缓存外使用整数值进行测试 我们的案例:我们有8辆小车=比较和所有操作都很顺利,因为我们从来没有PK高于128的底层数据库实体 你没有。整数缓存是integer的一个实现细节。如果使用整数,则接受缓存。这是一件好事,可以减少可能创建的有效重复对象的数量 用于定位虚假的整数引用比较,并将其替换为--这是解决所遇到问题的正确方法 如果您的应用程序中存在这种语言的基本问题,那么

最近偶然发现了一个与Java整数缓存相关的问题,我正在寻找一种禁用它的方法

现在测试是不可能的,因为我们不能说它有效,除非我们在缓存外使用整数值进行测试


我们的案例:我们有8辆小车
=比较和所有操作都很顺利,因为我们从来没有PK高于128的底层数据库实体

你没有。整数缓存是
integer
的一个实现细节。如果使用
整数
,则接受缓存。这是一件好事,可以减少可能创建的有效重复对象的数量

用于定位虚假的整数引用比较,并将其替换为--这是解决所遇到问题的正确方法


如果您的应用程序中存在这种语言的基本问题,那么我强烈建议您运行一整套静态分析测试,并对它们进行分类。

您可以使用Java选项设置缓存的大小。以下内容将允许您根据需要设置缓存:

-XX:AutoBoxCacheMax=<CACHE_SIZE>

解决和捕获此类bug最简单的方法是编写一个主键任意(和随机)高于128的单元测试

这将为您提供:

  • IntegerCache
  • 一种无需更改任何运行时参数即可独立验证此功能的方法(即,可在开发人员机箱上轻松重复)
  • 以测试形式提供的简明文档,说明您希望确保这些值实际得到了考虑

您不需要禁用JVM内部来测试这一点。您只需要了解它们的局限性,并在它们的情况对您的应用程序构成挑战时进行测试。

因为Java 6引入了Escape分析,所以我认为将Integer等临时对象集中在一起没有任何好处。此外,整数缓存“不可预测”有时会妨碍转义分析正常运行

如果启用了整数缓存,Java 8转义分析无法对整数对象进行标量替换。(Java13似乎在这两方面都做得很好)

官方不支持禁用整数缓存,但可以使用以下代码段执行此操作:

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();
    }
}
public static Unsafe getUnsafe(){
试一试{
字段theUnsafe=Unsafe.class.getDeclaredField(“theUnsafe”);
不安全。设置为可访问(true);
return(Unsafe)theUnsafe.get(null);
}捕获(NoSuchFieldException | IllegalArgumentException | IllegalAccessException e){
e、 printStackTrace();
返回null;
}
}
公共静态void disableIntegerCache(){
试一试{
Class clazz=Class.forName(“java.lang.Integer$IntegerCache”);
字段缓存=clazz.getDeclaredField(“缓存”);
字段低=clazz.getDeclaredField(“低”);
字段高=clazz.getDeclaredField(“高”);
不安全=getUnsafe();
对象库=不安全。staticFieldBase(低);
长低偏移=不安全。staticFieldOffset(低);
长高偏移=不安全。staticFieldOffset(高);
长缓存偏移=不安全。staticFieldOffset(缓存);
不安全。putObjectVolatile(基、cacheOffset、新整数[0]);
不安全。putIntVolatile(基、低偏移、整数、最大值);
不安全。putIntVolatile(基、高偏移量、整数.MIN_值);
}捕获(ClassNotFoundException | NoSuchFieldException | IllegalArgumentException e){
e、 printStackTrace();
}
}

我使用MAX_值和MIN_值是因为
valueOf
方法中与JVM内部函数相关的奇怪行为。

我几乎不认为不禁用缓存就不可能进行测试。如果需要未缓存的
整数
,请使用
新整数(1)初始化它。同时解雇与
进行对象比较的人员=。这个故事还有更多内容。你是如何比较这些整数的?它们都是物体吗?我敢打赌,编写该测试的开发人员假定在某个时候会发生取消装箱,但在您的代码中可能会发生这种情况吗?因为您现在知道了这个问题,所以可以轻松地更改测试,使主键值大于128。更好的解决方案是尝试破解
Integer
类。@Makoto,虽然我同意您不需要禁用缓存来进行测试,但这是问题的有效答案,因此我不认为有理由否决它。实际上,您无法使用此方法减小缓存大小。如果127大于此值,则使用127@Makoto显然这不是真正的答案。但我不认为在这里投反对票是合适的。它解决了问题,实际上是我不知道的。@GhostCat:如果这不是真正的答案,它怎么能解决任何问题@迈克尔,现在你的论点给了我们否决投票的理由。因为如果是真的,答案就是错的,因此没有回答这个问题!
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();
    }
}