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.
MutableSet.class
that is executed in runtime in your local environment. Is there a default method there? – Kitchens$plus
methods. There are no bridge methods in theArraySet
class, though. – BegirdMutableSet
? – Kitchensmapped
, so this can't be the problem. – BegirdCollection
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.class
file or you just assumed that default method is there because you see it in the source (.java
) file? – Kitchensjavap
– Begirdjavac
on command line? (I realize you can't answer this at the moment) – Primatologygradle build test
. – BegirdBUILD SUCCESSFUL
– Primatologyclean
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