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: reviews-unsubscr...@spark.apache.org
For additional commands, e-mail: reviews-h...@spark.apache.org

Reply via email to