benf.org : other : cfr : Java 8 Lambdas - Mystery 'getClass' with instance method refs. |
Consider the following code:
public void test(Stream<String> in) { Set<String> s = SetFactory.newSet(); Stream<Boolean> numbers = in.map(s::contains); }
public void test(java.util.stream.Stream); Code: 0: invokestatic #2 // Method org/benf/cfr/tests/support/SetFactory.newSet:()Ljava/util/Set; 3: astore_2 4: aload_1 5: aload_2 6: invokedynamic #3, 0 // InvokeDynamic #0:apply:(Ljava/util/Set;)Ljava/util/function/Function; 11: invokeinterface #4, 2 // InterfaceMethod java/util/stream/Stream.map:(Ljava/util/function/Function;)Ljava/util/stream/Stream; 16: astore_3 17: return
public void test(java.util.stream.Stream); Code: 0: invokestatic #2 // Method org/benf/cfr/tests/support/SetFactory.newSet:()Ljava/util/Set; 3: astore_2 4: aload_1 5: aload_2 6: dup 7: invokevirtual #3 // Method java/lang/Object.getClass:()Ljava/lang/Class; 10: pop 11: invokedynamic #4, 0 // InvokeDynamic #0:apply:(Ljava/util/Set;)Ljava/util/function/Function; 16: invokeinterface #5, 2 // InterfaceMethod java/util/stream/Stream.map:(Ljava/util/function/Function;)Ljava/util/stream/Stream; 21: astore_3 22: return
... interesting - B132 adds an explicit call to getClass on the Set s.
I haven't yet found any 'official' description of a reason for this - it seems (internet based wisdom) that it's a null check, though I imagine that it's there to force any issues with classLoading for s to occur in the explicit original method, as opposed to inside the invokedynamic's builder, thus causing users to get slightly more understandable stack traces in the case of problems.
CFR 0_75 will generate the following.
public void test(Stream<String> in) { Set s; Set set = s = SetFactory.newSet(); set.getClass(); Stream<Boolean> numbers = in.map(set::contains); }
.... but this is fixed in 0_76
public void test(Stream<String> in) { Set s = SetFactory.newSet(); Stream<Boolean> numbers = in.map(s::contains); }
Last updated 03/2014 |