默认方法返回true一段时间,然后返回false?(可能的JVM错误)

ski*_*iwi 66 java inheritance interface java-8

我有一个问题,下面的代码,我隔离到最封闭的形式,我使用Java 8,几乎准备好发布(2014年3月18日),所以我希望在实现本身没有严重的问题,所以它可能/必须是我自己的代码:

注意:代码是用Java 8编写的,它具有各种新功能,包括default接口中的方法实现.

public abstract class Drawable implements DrawableInterface {    

}
Run Code Online (Sandbox Code Playgroud)
interface DrawableInterface {
    default public boolean isShadowReceiver() {
        return false;
    }

    default public boolean isShadowCaster() {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)
public interface ShadowDrawable extends DrawableInterface {
    @Override
    default public boolean isShadowReceiver() {
        return true;
    }

    @Override
    default public boolean isShadowCaster() {
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)
public class Box extends Drawable implements ShadowDrawable {

}
Run Code Online (Sandbox Code Playgroud)
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();
    }
}
Run Code Online (Sandbox Code Playgroud)

代码本身可能没有多大意义,但这是因为我已经剥夺了大量其他不相关的方法.

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

isolatedbug.Box@5acf9800 C = true/R = true
isolatedbug.Box@5acf9800 C = true/R = true
isolatedbug.Box@5acf9800 C = true/R = true
isolatedbug.Box@5acf9800 C = true/R = true
isolatedbug. Box @ 5acf9800 C = false/R = false
isolatedbug.Box@5acf9800 C = false/R = false
isolatedbug.Box@5acf9800 C = false/R = false
isolatedbug.Box@5acf9800 C = false/R = false
isolatedbug.Box @ 5acf9800 C = false/R = false
isolatedbug.Box@5acf9800 C = false/R = false

它切换true到的时间false似乎取决于方法的调用次数,因为在两者之间睡眠时间越长,切换时间越长.

我正在运行此操作,以获取有关Windows 8 64位的完整信息,其中java -version:

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

任何人都可以向我解释发生了什么事吗?
我也很感激,如果其他人使用Java 8 -any build-,可以运行,看看他们是否有同样的问题.

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

  Properties p = System.getProperties();
  p.list(System.out);
Run Code Online (Sandbox Code Playgroud)

输出:

-- 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
Run Code Online (Sandbox Code Playgroud)

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

所以结论似乎是在我的特定用例中,代码的解释和JIT编译/内联变体是不一样的,因此在编译解释的代码之后它有可能从解释代码切换到编译,从而澄清输出开关.

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

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

rol*_*lfl 55

这是Java8中的已知错误.

请参阅此Jira:CHA在分析过程中忽略默认方法,导致代码生成错误

这篇博客文章很有启发性 ......

更新/摘要:


以前的注释

我转载了这个问题:

声称在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>
Run Code Online (Sandbox Code Playgroud)

添加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
}
Run Code Online (Sandbox Code Playgroud)

  • @skiwi它出现在[JDK-8036100](https://bugs.openjdk.java.net/browse/JDK-8036100),是的,它是P1. (5认同)
  • @skiwi ......它现在也"固定"了.很快就会有新的构建.修复是为默认方法禁用名为CHA的优化.[JDK-8036153](https://bugs.openjdk.java.net/browse/JDK-8036153)跟踪底层问题的真正修复. (5认同)
  • @skiwi我会再次受到谴责.您在Java 8 GA公告中提到了(最后一段):http://mreinhold.org/blog/jdk8-ga (4认同)
  • 博客文章声称问题也已修复!修复将在3月发布."更新:错误是修复的.原因是热点编译器过度优化.所以修复将成为3月官方JDK 8版本的一部分!所以我们可以再次使用接口中的默认方法而不用担心奇怪的行为." (2认同)
  • @DanTemple然而,这是博客声称的,所以我宁愿拥有它的官方来源. (2认同)
  • [Build b132](https://jdk8.java.net/download.html)应包含修复程序:http://download.java.net/jdk8/changes/jdk8-b132.html (2认同)