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

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

注意:代码是用Java 8编写的,它具有各种新特性,包括接口中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秒后看到一些奇怪的,特别是对我个人而言,我看到以下几点:

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运行时环境(build 1.8.0-b129)
Java HotSpot(TM)64位服务器虚拟机(构build25.0-b69,混合模式)

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

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

  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虚拟机选项,当它已经被使用时,它会像预期的那样返回true

因此,结论似乎是,在我的特殊用例中,代码的解释和JIT编译/内联变体是不相同的,因此它有可能在解释的代码被编译后从解释到编译切换,从而澄清输出开关。

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

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

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

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

这个博客条目是启发 ….

更新/总结:

  • 问题在b127之前确定,并在b127( JDK-8031695 )
  • 问题在b129( JDK-8036100 )中重新出现(或类似的问题出现)
  • 问题在b132( 可在这里find )已经“解决了”( 禁用失败的优化 )
  • 问题还logging了以后的“适当的”修复程序( 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> 

添加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 }