Strange Default Method behavior with different Java versions
Asked Answered
B

1

10

Let's say I have the following class hierarchy:

interface Collection<E>
{
    Collection<E> $plus(E element)
}

interface MutableCollection<E> extends Collection<E>
{
    @Override
    MutableCollection<E> $plus(E element)
}

interface Set<E> extends Collection<E>
{
    @Override
    Set<E> $plus(E element)
}

interface MutableSet<E> extends Set<E>, MutableCollection<E>
{
    @Override
    default MutableSet<E> $plus(E element)
    {
        // ... implementation
    }
}

abstract class AbstractArraySet<E> implements Set<E>
{
    // ... no $plus(...) implementation
}

class ArraySet<E> extends AbstractArraySet<E> implements MutableSet<E>
{
    // ... no $plus(...) implementation
}

As you can see, only the MutableSet class provides an implementation for the $plus method. In a Test case, I am calling this method on an instance of type ArraySet. The Test always passes in the CI environment, while it always fails with an AbstractMethodError on my local environment. In both cases, I am using Gradle (2.7).


The Error:

java.lang.AbstractMethodError: Method dyvil/collection/mutable/ArraySet.$plus(Ljava/lang/Object;)Ldyvil/collection/Collection; is abstract

    at dyvil.collection.mutable.ArraySet.$plus(ArraySet.java)
    at dyvil.tests.CollectionTests.testCollection(CollectionTests.java:99)
    at ...

Test Code:

testCollection(new ArraySet());

public void testCollection(Collection collection)
{
    assertEquals(mutable.$plus("newElement"), collection.$plus("newElement"));
}

java -version output:

  • CI (where it works):

    java version "1.8.0"
    Java(TM) SE Runtime Environment (build 1.8.0-b132)
    Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)
    
  • Local (where it fails):

    java version "1.8.0_71"
    Java(TM) SE Runtime Environment (build 1.8.0_71-b15)
    Java HotSpot(TM) 64-Bit Server VM (build 25.71-b15, mixed mode)
    

I am expecting this to be some sort of javac bug, where the compiler fails to add all required bridge methods (the code compiles without any warnings or errors). In IntelliJ IDEA, the problem occurs both using javac and the Eclipse Compiler.

Begird answered 31/1, 2016 at 14:39 Comment(17)
Are you presenting what you already proved to be the minimal setup to reproduce the error? There are a lot of interfaces here, if it can't be demostrated with fewer then the problem looks quite complex.Primatology
Decompile the MutableSet.class that is executed in runtime in your local environment. Is there a default method there?Kitchens
@DraganBozanovic, yes, there are bridge methods for all super-interface $plus methods. There are no bridge methods in the ArraySet class, though.Begird
No repro on "Netbeans with jdk1.8.0_65"Gazebo
What is your project structure? Is the code in which you do assertions in the same jar as MutableSet?Kitchens
I'd suggest reproducing without the dollar sign in the method name.Primatology
@DraganBozanovic check the Test Code link - it's all in the same project.Begird
@MarkoTopolnik the problem also occurs for methods with normal named like mapped, so this can't be the problem.Begird
And does it occur in any setting simpler than yours? If this is a compiler bug, it will be crucial to exactly delineate the circumstances where it occurs.Primatology
I can't test it right now, but I guess you could remove the Collection layer. I am not sure though, since that is what the error talks about. Will test as soon as I have access to my dev environment.Begird
Ok, did you decompile the .class file or you just assumed that default method is there because you see it in the source (.java) file?Kitchens
@DraganBozanovic I checked it with javapBegird
Locally, the problem manifests from IDEA only, or can you reproduce with plain javac on command line? (I realize you can't answer this at the moment)Primatology
I set it up in IDEA, with JDK 1.8.0_71, and couldn't reproduce.Primatology
@MarkoTopolnik I haven't tested it with javac, but I can reproduce it with Gradle on my local env. At the very least, you should be able to reproduce this problem by cloning the repo and running gradle build test.Begird
Did it: BUILD SUCCESSFULPrimatology
Turns out doing a full clean and rebuild fixed the problem for me as well. Nevertheless, there must have been a bug involved at some point that caused the faulty binaries. Thanks for you efforts, anyway.Begird
E
0

(Answer is made based on author's comment above: problem was solved):

Doing a full clean and rebuild fixed the problem as well.

Nevertheless, there must have been a bug involved at some point that caused the faulty binaries.

Extrusion answered 31/1, 2016 at 14:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.