Default method returns true for a while, and then returns false? (Possible JVM bug)
JavaInheritanceInterfaceJava 8Java Problem Overview
I have an issue with the following code, which I isolated to the most closed form, I am using Java 8, which is almost ready for launch (18 March 2014), so I expect no serious issues in the implementation itself, so it may/must be my own code:
Note: The code is written in Java 8, which has all kinds of new features, including default
method implementation in interfaces.
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();
}
}
The code in itself may not make most sense, but that is because I have stripped a load of other irrelevant methods.
However, when you observe the output, you see something strange, at a certain point, for me personally after 30 seconds, I see the following:
>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
The time when it switches from true
to false
, seems to depend on the number of calls the method, as with longer sleeps in between, it takes longer to switch.
I am running this, for full information on Windows 8 64-bit, with as 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)
Can anyone explain to me what is going on?
I'd also appreciate if others with Java 8 -any build-, could run and see if they have the same issue.
Some more information after using this code:
Properties p = System.getProperties();
p.list(System.out);
Output:
-- 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
I have also checked the -Xint
VM option, when this has been used, it returns true
as expected.
So the conclusion seems to be that in my particular use case, the interpreted and JIT compiled/inlined variants of the code are not the same and hence it is a possibility that after the interpreted code is compiled it switches from interpreted to compiled and thus clarifying the switch in output.
Adding the -Xint
option to the actual program in which the bug occured, has also fixed the issue there.
The official bug report has been accepted: JIRA Bug JDK-8036100
Java Solutions
Solution 1 - Java
This is a known bug in Java8.
See this Jira: CHA ignores default methods during analysis leading to incorrect code generation
This blog entry is enlightening....
Update / Summary:
- issue identified before b127, and fixed in b127 ( JDK-8031695 )
- issue reappeared (or a similar issue appeared) in b129 ( JDK-8036100 )
- issue has been 'worked around' (disable the optimization that was failing) in b132 ( available here )
- issue also logged for a 'proper' fix for later ( JDK-8036153 )
Previous Notes
I have reproduced this issue with:
Claims that this issue is resolved in b127 are confusing since I see it clearly in b129 (unless I am confused about the JVM version conventions...)
> 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>
Adding 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 > }