Github user retronym commented on the issue:
https://github.com/apache/spark/pull/19675
It just occurred to me that my answer above, discussing ways to access the
bytecode of the lambda class, aren't really relevant here. The structure of the
lambda class is always the same: it just passes the captures and the function
parameters to the lambda implementation method, which is hosted in the class
that encloses the lambda. You could analyse the body of this method to see if
you can find any unused captures (even though scalac has already endeavoured to
do this).
Let's look at a concrete example:
```
cala> def inspect(closure: Object) = { val writeReplace =
closure.getClass.getDeclaredMethod("writeReplace");
writeReplace.setAccessible(true);
writeReplace.invoke(closure).asInstanceOf[java.lang.invoke.SerializedLambda]}
inspect: (closure: Object)java.lang.invoke.SerializedLambda
scala> :paste -raw
// Entering paste mode (ctrl-D to finish)
package p1; class C { def c = "c"; class D { def test = (x: String) => c +
x } }
// Exiting paste mode, now interpreting.
scala> val c = new p1.C; val d = new c.D; val closure = d.test; val sl =
inspect(closure)
c: p1.C = p1.C@5034681f
d: c.D = p1.C$D@1dfe5dd1
closure: String => String = p1.C$D$$Lambda$1160/155129334@1fe05fff
sl: java.lang.invoke.SerializedLambda =
SerializedLambda[capturingClass=class p1.C$D,
functionalInterfaceMethod=scala/Function1.apply:(Ljava/lang/Object;)Ljava/lang/Object;,
implementation=invokeStatic
p1/C$D.$anonfun$test$1:(Lp1/C$D;Ljava/lang/String;)Ljava/lang/String;,
instantiatedMethodType=(Ljava/lang/String;)Ljava/lang/String;, numCaptured=1]
scala> :javap p1.C$D#$anonfun$test$1
public static final java.lang.String $anonfun$test$1(p1.C$D,
java.lang.String);
descriptor: (Lp1/C$D;Ljava/lang/String;)Ljava/lang/String;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: new #51 // class
java/lang/StringBuilder
3: dup
4: invokespecial #55 // Method
java/lang/StringBuilder."<init>":()V
7: aload_0
8: invokevirtual #57 // Method
p1$C$D$$$outer:()Lp1/C;
11: invokevirtual #61 // Method
p1/C.c:()Ljava/lang/String;
14: invokevirtual #65 // Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_1
18: invokevirtual #65 // Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #68 // Method
java/lang/StringBuilder.toString:()Ljava/lang/String;
24: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 25 0 $this Lp1/C$D;
0 25 1 x Ljava/lang/String;
LineNumberTable:
line 1: 0
MethodParameters:
Name Flags
$this final synthetic
x
```
---
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]