JDK-8026742 : DefaultMethodsTest.java fails expecting AbstractMethodError
  • Type: Bug
  • Component: tools
  • Affected Version: 8
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2013-10-16
  • Updated: 2014-09-29
  • Resolved: 2013-11-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8Fixed
Related Reports
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Duplicate :  
Relates :  
Relates :  
Sub Tasks
JDK-8027220 :  
Description
Recent changes to in hotspot to support private methods in interfaces resulted in a specified behavioural change such that DefaultMethodsTest previously expected AbstractMethodError but should now expect IncompatibleClassChangeError or successful completion.  Additionally, one test should still expect AbstractMethodError but IncompatibleClassChangeError is now incorrectly being thrown.

The JDK version of this test (to which this bug initially applied) has been removed.  This bug now applies to the matching version in the langtools repo: tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java.

Tests in the lambda repo, jdk/lambda/vm/FDSeparateCompilationTest.java, are also affected.

The relevant tests are ---

testAmbiguousReabstract
    current test expects: AME
    new spec: successful invocation
    current behavior: ICCE

testConflict
    current test expects: AME
    new spec: ICCE
    current behavior: ICCE

testSuperConflict
    current test expects: AME
    new spec: ICCE
    current behavior: invocation

testSuperDisqual
    current test expects: AME
    new spec: successful invocation
    current behavior: invocation

testSuperGenericDisqual
    current test expects: AME
    new spec: successful invocation
    current behavior: invocation

testSuperNull
    current test expects: AME
    new spec: AME
    current behavior: ICCE



Comments
All dependent bugs have now been fixed, and found there way to TL. All tests pass in master testing. This test passes in TL specific testing. Thus I will now close this bug.
27-11-2013

Adding aurora rule to get test matched RULE tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java Exception java.lang.AssertionError: Exception should have been thrown
30-10-2013

Current status: JDK-8027304 -- testAmbiguousReabstract test / new spec: successful invocation current behavior: ICCE JDK-8027229 -- testSuperConflict test / new spec: ICCE current behavior: invocation JDK-8026299 -- testSuperNull test / new spec: AME current behavior: ICCE
30-10-2013

Adding exceptions to match it in Aurora: Exception: java.lang.AssertionError: expected [class java.lang.AbstractMethodError] but found [class java.lang.IncompatibleClassChangeError] Exception: java.lang.AssertionError: Exception should have been thrown Exception: java.lang.Exception: failures: 5
29-10-2013

Adding test case name to match it in Aurora: tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java
29-10-2013

The testSuperNull should be covered under JDK-8026299. So that leaves testAmbiguousReabstract as not categorized. I doubt the ASM fixes affect testAmbiguousReabstract since it does not utilize lambda expressions or MHs and therefore the relevant code to generate class files, using ASM, will never kick in. (To verify i ran DefaultMethodsTest with and without the ASM patch applied and there was no change in the results.) Thus this issue is not blocked by the ASM issues.
25-10-2013

With the test updated to match the spec (push winding its way through the system now), the failures are now: testAmbiguousReabstract test / new spec: successful invocation current behavior: ICCE testSuperConflict test / new spec: ICCE current behavior: invocation testSuperNull test / new spec: AME current behavior: ICCE ---- The testSuperConflict error is covered under JDK-8027229. Are we assuming the ASM fixes will fix the other two?
25-10-2013

This bug is blocked 2 JVM issues which will not be fixed for ZBB, therefore, not available in TL until at least Oct 31st.
24-10-2013

Adding test name to get it matched in Aurora: tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java
23-10-2013

Removed redundant JDK version. Exact same issues effect langtools version, so converted this to langtools test bug.
23-10-2013

Updated patch including OW2 feedback and Paul S's observation that the class file version need bumping in java.lang.invoke.* code.
23-10-2013

Removed the "teststabiization" label, gathered enough data to suggest that there might be a regression in the VM even if some aspects of the test will require updating when the VM is fixed.
22-10-2013

Attached "testSuperConflict_ICCE_or_AME_or_none.zip" is a stand alone test case for testSuperNull that fails to produce an IncompatibleChangeError. The invocation of the default method wires up to K.m(), which is the first interface J extends from: interface J extends K,L { } [6403] static jint IV_C.m() [6403] 1220669 3 0x0000000169387428 0x0000000104273f10 dup [6403] 1220670 4 0x0000000169387428 0x0000000104273f10 invokespecial 3 <C.<init>()V> [6403] virtual void C.<init>() [6403] 1220671 0 0x00000001047727a0 0x0000000000000008 aload_0 [6403] 1220672 1 0x0000000169387428 0x00000000000000db invokespecial 1 <java/lang/Object.<init>()V> [6403] 1220673 4 0x0000000169387428 0x0000000000000000 return [6403] static jint IV_C.m() [6403] 1220674 7 0x0000000030000021 0x0000000000000004 invokevirtual 4 <C.m()I> [6403] virtual jint I.m() [6403] 1220675 0 0x00000001047727a8 0x0000000000000008 aload_0 [6403] 1220676 1 0x0000000169387428 0x00000000000000db invokespecial 1 <J.m()I> [6403] virtual jint K.m() [6403] 1220677 0 0x0000000104772750 0x0000000000000008 bipush 99 [6403] 1220678 2 0x0000000000000063 0x0000000000000008 ireturn [6403] virtual jint I.m() [6403] 1220679 4 0x0000000000000063 0x0000000000000000 ireturn [6403] static jint IV_C.m() [6403] 1220680 10 0x0000000000000063 0x0000000000000008 ireturn [6403] static void IV_C.main(jobject) [6403] 1220681 6 0x0000000000000063 0x0000000000000010 invokevirtual 7 <java/io/PrintStream.println(I)V> Change the order to "extends L, K" and invocation wires up to L.m().
22-10-2013

Attached "testSuperNull_ICCE_or_AME.zip" is a stand alone test case for testSuperNull that reproduces the ICCE. The byte code for interface I and J are respectively: interface I extends J SourceFile: "I.java" minor version: 0 major version: 52 flags: ACC_INTERFACE, ACC_ABSTRACT Constant pool: #1 = InterfaceMethodref #4.#11 // J.m:()I #2 = Class #12 // I #3 = Class #13 // java/lang/Object #4 = Class #14 // J #5 = Utf8 m #6 = Utf8 ()I #7 = Utf8 Code #8 = Utf8 LineNumberTable #9 = Utf8 SourceFile #10 = Utf8 I.java #11 = NameAndType #5:#6 // m:()I #12 = Utf8 I #13 = Utf8 java/lang/Object #14 = Utf8 J { public int m(); descriptor: ()I flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // InterfaceMethod J.m:()I 4: ireturn LineNumberTable: line 3: 0 } interface J SourceFile: "J.java" minor version: 0 major version: 52 flags: ACC_INTERFACE, ACC_ABSTRACT Constant pool: #1 = Class #7 // J #2 = Class #8 // java/lang/Object #3 = Utf8 m #4 = Utf8 ()I #5 = Utf8 SourceFile #6 = Utf8 J.java #7 = Utf8 J #8 = Utf8 java/lang/Object { public abstract int m(); descriptor: ()I flags: ACC_PUBLIC, ACC_ABSTRACT } So I is correctly referring to J.m() using CONSTANT_InterfaceMethodref. The VM appears to be confused and thinks the default method on interface J is a class (static) method: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokespecial.linking-120 ", if the resolved method is a class (static) method, the invokespecial instruction throws an IncompatibleClassChangeError." Rather than (as Dan points out): http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokespecial.runtime-120 ", if the selected method is abstract, invokespecial throws an AbstractMethodError" The result of this standalone test is not affected by applying the ASM patch (since there are no lambda expressions or method references in the default methods)
22-10-2013

Updated ASM patch, with adjustments suggested by ASM community. The InnerClassLambdaMetafactory is patched to call the new ASM API.
22-10-2013

I applied John's ASM patch (in both tl and lambda) but it did not change the results reported by DefaultMethodsTest.
18-10-2013

Added "sqebug" label to make Aurora match it as "knownfailure" Affected test: jdk/lambda/vm/DefaultMethodsTest.java
18-10-2013

ASM currently always emits CONSTANT_Methodref for invokespecial instructions. This *should* elicit an ICCE. A tweak to ASM should get past that particular ICCE; there may be others. See https://bugs.openjdk.java.net/secure/attachment/16646/asm-intfc.zip for a possible fix.
17-10-2013

And DefaultMethodsTest.testSuperConflict: (The test expects an AME, but I'm told gets no error.) /** * interface K { int m() default { return 99; } } * interface L { int m() default { return 101; } } * interface J extends K, L {} * interface I extends J, K { int m() default { J.super.m(); } } * class C implements I {} * * TEST: C c = new C(); c.m() throws AME * TODO: add case for K k = new C(); k.m() throws AME */ In this case, the specified behavior of invokespecial is an ICCE: "if more than one of the maximally-specific matching methods is not abstract, an IncompatibleClassChangeError is raised".
16-10-2013

Here's an evaluation of the DefaultMethodsTest.testSuperNull failure: --- interface J { int m(); } interface I extends J { default int m() { return J.super.m(); } } class C implements I {} C c = new C(); c.m(); // expected: AME; actual: ICCE --- I agree that this should be an AME. c.m invokes I.m, and I.m in turn calls J.super.m. Per the invokespecial spec, "if the selected method is abstract, invokespecial throws an AbstractMethodError". (This won't compile directly, because the J.super.m call would be an error, but I'm assuming the manipulations in the body of the test are there to get to this state via separate compilation.) Looking at the error message: Exception in thread "main" java.lang.IncompatibleClassChangeError: Found interface J, but class was expected This may be a problem with the generated classes? Maybe a Methodref is being used in the constant pool, when an InterfaceMethodref is needed? It's possible this is an old bug in the test that Hotspot neglected to catch before but is catching now...
16-10-2013

Tests testSuperConflict, testSuperDisqual and testSuperGenericDisqual expect AME but no exception is thrown.
16-10-2013

This test has been failing intermittently in jdk8/tl for some time but started to fail every time after picking up hotspot changes from jdk8/jdk8.
16-10-2013