当前位置: 首页 > 知识库问答 >
问题:

默认方法一会儿返回true,一会儿又返回false?(可能是JVM bug)

黄锋
2023-03-14

我对以下代码有问题,我将其隔离为最封闭的形式,我正在使用Java8,它几乎准备好发布(2014年3月18日),所以我预计在实现本身不会有严重的问题,所以它可能/必须是我自己的代码:

注意:代码是用Java8编写的,它具有各种新特性,包括接口中的default方法实现。

public abstract class Drawable implements DrawableInterface {    

}
interface DrawableInterface {
    default public boolean isShadowReceiver() {
        return false;
    }

    default public boolean isShadowCaster() {
        return false;
    }
}
public interface ShadowDrawable extends DrawableInterface {
    @Override
    default public boolean isShadowReceiver() {
        return true;
    }

    @Override
    default public boolean isShadowCaster() {
        return true;
    }
}
public class Box extends Drawable implements ShadowDrawable {

}
public class IsolatedBug {
    private final Box box;

    private final List<Drawable> drawables;

    public IsolatedBug() {
        this.box = new Box();
        this.drawables = new ArrayList<>();

        drawables.add(box);
        drawables.forEach(drawable -> System.out.println(drawable + " C=" + drawable.isShadowCaster() + "/R=" + drawable.isShadowReceiver()));
    }

    private void init() throws InterruptedException {
        while (true) {
            drawables.forEach(drawable -> System.out.println(drawable + " C=" + drawable.isShadowCaster() + "/R=" + drawable.isShadowReceiver()));
            Thread.sleep(100);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new IsolatedBug().init();
    }
}

代码本身可能不是最有意义的,但那是因为我已经剥离了其他不相关方法的负载。

但是,当您观察输出时,您会看到一些奇怪的东西,在某个时刻,对于我个人来说,30秒后,我看到以下内容:

孤立的bug。box @ 5 ACF 9800 C = true/R = true < br > isolated bug。box @ 5 ACF 9800 C = true/R = true < br > isolated bug。box @ 5 ACF 9800 C = true/R = true < br > isolated bug。box @ 5 ACF 9800 C = true/R = true < br > isolated bug。Box@5acf9800 C=false/R=false。Box@5acf9800 C=false/R=false。Box@5acf9800 C=false/R=false。Box@5acf9800 C=false/R=false。Box@5acf9800 C=false/R=false。Box@5acf9800 C=false/R=false

它从true切换到false的时间似乎取决于方法的调用次数,因为中间睡眠时间越长,切换时间就越长。

我正在运行此程序,以获取有关64位Windows 8的完整信息,使用的是< code>java -version:

Java版本"1.8.0"
Java(TM)SE运行时环境(build 1.8.0-b129)
JavaHotSpot(TM)64位服务器VM(build 25.0-b69,混合模式)

有人能给我解释一下发生了什么吗?
如果Java8的其他人——任何建筑——能跑去看看他们是否有同样的问题,我也会很感激。

使用此代码后的更多信息:

  Properties p = System.getProperties();
  p.list(System.out);

输出:

-- listing properties --
java.runtime.name=Java(TM) SE Runtime Environment
sun.boot.library.path=C:\Program Files\Java\jdk1.8.0\jre\bin
java.vm.version=25.0-b69
java.vm.vendor=Oracle Corporation
java.vendor.url=http://java.oracle.com/
path.separator=;
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
file.encoding.pkg=sun.io
user.script=
user.country=NL
sun.java.launcher=SUN_STANDARD
sun.os.patch.level=
java.vm.specification.name=Java Virtual Machine Specification
user.dir=C:\Users\Frank\Dropbox\NetbeansProjec...
java.runtime.version=1.8.0-b129
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs=C:\Program Files\Java\jdk1.8.0\jre\li...
os.arch=amd64
java.io.tmpdir=C:\Users\Frank\AppData\Local\Temp\
line.separator=

java.vm.specification.vendor=Oracle Corporation
user.variant=
os.name=Windows 8.1
sun.jnu.encoding=Cp1252
java.library.path=C:\Program Files\Java\jdk1.8.0\bin;C:...
java.specification.name=Java Platform API Specification
java.class.version=52.0
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
os.version=6.3
user.home=C:\Users\Frank
user.timezone=
java.awt.printerjob=sun.awt.windows.WPrinterJob
file.encoding=UTF-8
java.specification.version=1.8
user.name=Beheerder
java.class.path=C:\Users\Frank\Dropbox\NetbeansProjec...
java.vm.specification.version=1.8
sun.arch.data.model=64
java.home=C:\Program Files\Java\jdk1.8.0\jre
sun.java.command=isolatedbug.IsolatedBug
java.specification.vendor=Oracle Corporation
user.language=nl
awt.toolkit=sun.awt.windows.WToolkit
java.vm.info=mixed mode
java.version=1.8.0
java.ext.dirs=C:\Program Files\Java\jdk1.8.0\jre\li...
sun.boot.class.path=C:\Program Files\Java\jdk1.8.0\jre\li...
java.vendor=Oracle Corporation
file.separator=\
java.vendor.url.bug=http://bugreport.sun.com/bugreport/
sun.cpu.endian=little
sun.io.unicode.encoding=UnicodeLittle
sun.desktop=windows
sun.cpu.isalist=amd64

我还检查了 -Xint VM 选项,当使用此选项时,它会按预期返回 true

因此,结论似乎是,在我的特定用例中,代码的解释变体和JIT编译/内联变体是不同的,因此,在编译解释代码后,可能会从解释代码切换到编译代码,从而明确输出中的切换。

-Xint选项添加到发生错误的实际程序中,也解决了那里的问题。

官方错误报告已被接受:JIRA 漏洞 JDK-8036100

共有1个答案

暴博远
2023-03-14

这是Java8中的一个已知错误。

请看这个吉拉:CHA在分析过程中忽略默认方法,导致不正确的代码生成

这个博客条目很有启发性....

  • 在 b127 之前发现的问题,并在 b127 中修复 ( JDK-8031695 )
  • 问题在b129中重新出现(或出现类似的问题) ( JDK-8036100 )
  • 问题已在b132中“解决”(禁用失败的优化)(可在此处获得)
  • 还记录了稍后的“正确”修复程序 ( JDK-8036153 )

我通过以下方式重现了此问题:

声称这个问题在b127中得到解决是令人困惑的,因为我在b129中清楚地看到了它(除非我对JVM版本约定感到困惑…)

C:\Java8\jdk-1.8.0_01\bin>java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b129)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b69, mixed mode)

C:\Java8\jdk-1.8.0_01\bin>

Add System.out.println(System.getProperties());

{
java.runtime.name=Java(TM) SE Runtime Environment, 
java.runtime.version=1.8.0-b129, 
java.vm.specification.name=Java Virtual Machine Specification, 
java.vm.name=Java HotSpot(TM) 64-Bit Server VM, 
java.vm.version=25.0-b69, 
java.vm.vendor=Oracle Corporation, 
java.vendor.url=http://java.oracle.com/, 
java.vm.specification.version=1.8, 
java.specification.name=Java Platform API Specification, 
java.specification.version=1.8, 
java.specification.vendor=Oracle Corporation, 
java.class.version=52.0, 
sun.boot.library.path=C:\Java8\jdk-1.8.0_01\jre\bin, 
sun.java.launcher=SUN_STANDARD, 
sun.os.patch.level=Service Pack 1, 
java.endorsed.dirs=C:\Java8\jdk-1.8.0_01\jre\lib\endorsed, 
os.arch=amd64, 
java.vm.specification.vendor=Oracle Corporation, 
os.name=Windows 7, 
sun.jnu.encoding=Cp1252, 
java.library.path=C:\Java8\jdk-1.8.0_01\bin;......, 
sun.management.compiler=HotSpot 64-Bit Tiered Compilers, 
os.version=6.1, 
file.encoding=UTF-8, 
sun.java.command=fromso.IsolatedBug, 
java.home=C:\Java8\jdk-1.8.0_01\jre, 
sun.arch.data.model=64, 
user.language=en, 
java.ext.dirs=C:\Java8\jdk-1.8.0_01\jre\lib\ext;C:\windows\Sun\Java\lib\ext,

sun.boot.class.path=C:\Java8\jdk-1.8.0_01\jre\lib\resources.jar;......,
java.vendor=Oracle Corporation, 
file.separator=\, 
java.vendor.url.bug=http://bugreport.sun.com/bugreport/, 
sun.io.unicode.encoding=UnicodeLittle, 
sun.cpu.endian=little, 
sun.desktop=windows, 
sun.cpu.isalist=amd64
}
 类似资料:
  • 问题内容: 当我尝试从Java代码中删除tomcat服务器conf / Catalina / localhost中存在的文件时,file.delete()始终返回false。但是,如果我通过file.exists()函数检查文件,它将返回true。我没有任何例外。请帮助我们为什么会这样。有什么解决方案? 问题答案: 当我尝试从Java代码中删除tomcat服务器conf / Catalina /

  • 问题内容: 据我所知,使用或实例化对象分别返回或的新实例。具有 新标识 的新实例对象。 在我实际测试它之前,这对我来说是很清楚的,我注意到它实际上返回了而不是预期的: 如预期的那样,分别使用和创建对象时,也会表现出这种行为: 我可以在状态文档中找到唯一相关的信息: […]例如,return和return 。 如果未提供任何参数,则构造函数将创建一个新的空元组。 可以说,这不足以回答我的问题。 那么

  • 问题内容: 这怎么可能? 这是 您会看到它应该在这里: 到底是怎么回事? 问题答案: (此答案中的代码已针对Swift 3及更高版本进行了更新。) 显然,您的变量是a (描述文件路径)。要以字符串形式获取路径,请使用属性,而不是: 以字符串格式(包括方案等)返回URL 。 例:

  • 问题内容: 它们没有正确回答(或根本没有回答)。但是,我不知道为什么总是对我返回false。有人可以告诉我为什么以及如何解决问题?提前致谢。 注意:我所说的活动是包含在中的孩子,这都不是 MAIN 或 LAUNCHER 活动。我不知道这有什么区别。 编辑: 因此应用程序不会进入后台。我希望它进入后台,就像按下硬件HOME一样 问题答案: 我不知道为什么要回去给你。也许您的清单上有些奇怪?无论如何,

  • 我正在尝试使用equals方法与对象进行比较,但它总是返回false

  • 在WordPress主题中,当一个联系人表单完成时,一条消息会写在页面上,但不会写在我想要的位置。但是当在PHP代码中更改消息的位置时,联系人表单中的段落(写在文章中)不再显示。事实上,我认为方法返回false,因此不会调用方法。 以下是原始代码: 我希望它是这样的: 如你所见,我只更改了确认消息的位置。但是在第二种方式中,具有的条件似乎不是真的,因为我在文章中写的文本没有显示出来。 有人能帮我解