IncompatibleClassChangeError example
Remi Forax
forax at univ-mlv.fr
Wed Jun 19 11:09:40 PDT 2013
On 06/19/2013 05:33 PM, Paul Sandoz wrote:
> Hi Peter.
>
> Replace "this.get()" with just "get()" or "Value.this.get()" and it runs OK, but i am not even sure it is entirely correct looking at the diffs of javap output of not this vs. this.
>
> e.g. public vs. private static interface for the method lambda$0.
>
>
> When using "this.get()" the following method is generated by javac:
>
> private static java.lang.Object lambda$0(java.util.function.Function);
> flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
> Code:
> stack=2, locals=1, args_size=1
> 0: aload_0
> 1: aload_0
> 2: invokeinterface #4, 1 // InterfaceMethod get:()Ljava/lang/Object;
> 7: invokeinterface #5, 2 // InterfaceMethod java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
> 12: areturn
> LineNumberTable:
> line 1: 0
> line 9: 2
>
> To my untrained eye that looks dodgy with the two aload_0 instructions, it's trying to invoked the Value.get method on the Function interface. I would expect the method to have two args.
>
> Paul.
yes, more precisely, lambda$0 should have only one parameter (the
Function) and the method should not be static (so 'this' is available),
So javac has trouble with 'this' inside a default method of an interface.
Rémi
>
> 16c16
> < #36 invokeinterface Test$Value.lambda$0:(Ljava/util/function/Function;)Ljava/lang/Object;
> ---
>> #36 invokestatic Test$Value.lambda$0:(Ljava/util/function/Function;)Ljava/lang/Object;
> 23c23
> < #2 = InvokeDynamic #0:#38 // #0:lambda$:(LTest$Value;Ljava/util/function/Function;)Ljava/util/function/Supplier;
> ---
>> #2 = InvokeDynamic #0:#38 // #0:lambda$:(Ljava/util/function/Function;)Ljava/util/function/Supplier;
> 57c57
> < #36 = MethodHandle #9:#49 // invokeinterface Test$Value.lambda$0:(Ljava/util/function/Function;)Ljava/lang/Object;
> ---
>> #36 = MethodHandle #6:#49 // invokestatic Test$Value.lambda$0:(Ljava/util/function/Function;)Ljava/lang/Object;
> 59c59
> < #38 = NameAndType #51:#52 // lambda$:(LTest$Value;Ljava/util/function/Function;)Ljava/util/function/Supplier;
> ---
>> #38 = NameAndType #51:#52 // lambda$:(Ljava/util/function/Function;)Ljava/util/function/Supplier;
> 73c73
> < #52 = Utf8 (LTest$Value;Ljava/util/function/Function;)Ljava/util/function/Supplier;
> ---
>> #52 = Utf8 (Ljava/util/function/Function;)Ljava/util/function/Supplier;
> 95c95
> < stack=4, locals=2, args_size=2
> ---
>> stack=3, locals=2, args_size=2
> 98,102c98,101
> < 4: aload_0
> < 5: aload_1
> < 6: invokedynamic #2, 0 // InvokeDynamic #0:lambda$:(LTest$Value;Ljava/util/function/Function;)Ljava/util/function/Supplier;
> < 11: invokespecial #3 // Method Test$SuppliedValue."<init>":(Ljava/util/function/Supplier;)V
> < 14: areturn
> ---
>> 4: aload_1
>> 5: invokedynamic #2, 0 // InvokeDynamic #0:lambda$:(Ljava/util/function/Function;)Ljava/util/function/Supplier;
>> 10: invokespecial #3 // Method Test$SuppliedValue."<init>":(Ljava/util/function/Supplier;)V
>> 13: areturn
> 107,108c106,107
> < 0 15 0 this LTest$Value;
> < 0 15 1 mapper Ljava/util/function/Function;
> ---
>> 0 14 0 this LTest$Value;
>> 0 14 1 mapper Ljava/util/function/Function;
> 111,112c110,111
> < 0 15 0 this LTest$Value<TT;>;
> < 0 15 1 mapper Ljava/util/function/Function<-TT;+TR;>;
> ---
>> 0 14 0 this LTest$Value<TT;>;
>> 0 14 1 mapper Ljava/util/function/Function<-TT;+TR;>;
> 115,116c114,115
> < public java.lang.Object lambda$0(java.util.function.Function);
> < flags: ACC_PUBLIC, ACC_SYNTHETIC
> ---
>> private static java.lang.Object lambda$0(java.util.function.Function);
>> flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
> 118,119c117,118
> < stack=2, locals=2, args_size=2
> < 0: aload_1
> ---
>> stack=2, locals=1, args_size=1
>> 0: aload_0
> 127,132d125
> < LocalVariableTable:
> < Start Length Slot Name Signature
> < 0 13 0 this LTest$Value;
> < LocalVariableTypeTable:
> < Start Length Slot Name Signature
> < 0 13 0 this LTest$Value<TT;>;
>
>
>
> On Jun 18, 2013, at 9:29 AM, Peter Levart <peter.levart at gmail.com> wrote:
>
>> Just a reminder that the following problem is still present...
>>
>> Regards, Peter
>>
>> On 06/09/2013 05:24 PM, Peter Levart wrote:
>>> Hi,
>>>
>>> When I compile and run the following program with the latest tip of
>>> lambda repo:
>>>
>>>
>>> import java.util.function.Function;
>>> import java.util.function.Supplier;
>>>
>>> public class ICCEBug {
>>>
>>> interface Value<T> extends Supplier<T> {
>>> default <R> Value<R> map(Function<? super T, ? extends R>
>>> mapper) {
>>> return new SuppliedValue<>(() -> mapper.apply(this.get()));
>>> }
>>> }
>>>
>>> static class SuppliedValue<T> implements Value<T> {
>>> private final Supplier<T> supplier;
>>>
>>> SuppliedValue(Supplier<T> supplier) {
>>> this.supplier = supplier;
>>> }
>>>
>>> @Override
>>> public T get() {
>>> return supplier.get();
>>> }
>>> }
>>>
>>> public static void main(String[] args) {
>>> Value<String> name = () -> "Peter";
>>> Value<String> sentence = name.map(nm -> "Hello " + nm + "!");
>>> System.out.println(sentence.get());
>>> }
>>> }
>>>
>>>
>>>
>>> ... I get the following exception:
>>>
>>> Exception in thread "main" java.lang.IncompatibleClassChangeError:
>>> Class ICCEBug$$Lambda$2 does not implement the requested interface
>>> ICCEBug$Value
>>> at ICCEBug$Value.lambda$0(ICCEBug.java:17)
>>> at ICCEBug$Value$$Lambda$3.get(Unknown Source)
>>> at ICCEBug$SuppliedValue.get(ICCEBug.java:30)
>>> at ICCEBug.main(ICCEBug.java:37)
>>>
>>>
>>>
>>> It looks like something is not compiled correctly.
>>>
>>> Regards, Peter
>>>
>>
>
More information about the lambda-dev
mailing list