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