luontola / retrolambda

Backport of Java 8's lambda expressions to Java 7, 6 and 5

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

java.lang.invoke classes left in constant pool

shannah opened this issue · comments

After running retrolambda on a class, the constant pool still retains class constants for java.lang.invoke classes (e.g. MethodHandles.Lookup).

Here is the output of java -p on such a class.

Classfile /private/var/folders/k7/b5qdhxt88v58wp008k8yxy180000gn/T/build8771077083861352612xxx/Classes_retrolamda/com/codename1/test/retrolambda/RetroLambdaTest.class
  Last modified 2-Jul-2015; size 1988 bytes
  MD5 checksum 210c986e156d02f4f872a760f4f3575a
  Compiled from "RetroLambdaTest.java"
public class com.codename1.test.retrolambda.RetroLambdaTest
  SourceFile: "RetroLambdaTest.java"
  InnerClasses:
       public static final #10= #7 of #9; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
  minor version: 0
  major version: 49
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Utf8               com/codename1/test/retrolambda/RetroLambdaTest
   #2 = Class              #1             //  com/codename1/test/retrolambda/RetroLambdaTest
   #3 = Utf8               java/lang/Object
   #4 = Class              #3             //  java/lang/Object
   #5 = Utf8               RetroLambdaTest.java
   #6 = Utf8               java/lang/invoke/MethodHandles$Lookup
   #7 = Class              #6             //  java/lang/invoke/MethodHandles$Lookup
   #8 = Utf8               java/lang/invoke/MethodHandles
   #9 = Class              #8             //  java/lang/invoke/MethodHandles
  #10 = Utf8               Lookup
  #11 = Utf8               current
  #12 = Utf8               Lcom/codename1/ui/Form;
  #13 = Utf8               <init>
  #14 = Utf8               ()V
  #15 = NameAndType        #13:#14        //  "<init>":()V
  #16 = Methodref          #4.#15         //  java/lang/Object."<init>":()V
  #17 = Utf8               this
  #18 = Utf8               Lcom/codename1/test/retrolambda/RetroLambdaTest;
  #19 = Utf8               init
  #20 = Utf8               (Ljava/lang/Object;)V
  #21 = Utf8               context
  #22 = Utf8               Ljava/lang/Object;
  #23 = Utf8               start
  #24 = NameAndType        #11:#12        //  current:Lcom/codename1/ui/Form;
  #25 = Fieldref           #2.#24         //  com/codename1/test/retrolambda/RetroLambdaTest.current:Lcom/codename1/ui/Form;
  #26 = Utf8               com/codename1/ui/Form
  #27 = Class              #26            //  com/codename1/ui/Form
  #28 = Utf8               show
  #29 = NameAndType        #28:#14        //  show:()V
  #30 = Methodref          #27.#29        //  com/codename1/ui/Form.show:()V
  #31 = Utf8               testLambdas
  #32 = NameAndType        #31:#14        //  testLambdas:()V
  #33 = Methodref          #2.#32         //  com/codename1/test/retrolambda/RetroLambdaTest.testLambdas:()V
  #34 = Utf8               stop
  #35 = Utf8               com/codename1/ui/Display
  #36 = Class              #35            //  com/codename1/ui/Display
  #37 = Utf8               getInstance
  #38 = Utf8               ()Lcom/codename1/ui/Display;
  #39 = NameAndType        #37:#38        //  getInstance:()Lcom/codename1/ui/Display;
  #40 = Methodref          #36.#39        //  com/codename1/ui/Display.getInstance:()Lcom/codename1/ui/Display;
  #41 = Utf8               getCurrent
  #42 = Utf8               ()Lcom/codename1/ui/Form;
  #43 = NameAndType        #41:#42        //  getCurrent:()Lcom/codename1/ui/Form;
  #44 = Methodref          #36.#43        //  com/codename1/ui/Display.getCurrent:()Lcom/codename1/ui/Form;
  #45 = Utf8               destroy
  #46 = Utf8               Lambda Test
  #47 = String             #46            //  Lambda Test
  #48 = Utf8               (Ljava/lang/String;)V
  #49 = NameAndType        #13:#48        //  "<init>":(Ljava/lang/String;)V
  #50 = Methodref          #27.#49        //  com/codename1/ui/Form."<init>":(Ljava/lang/String;)V
  #51 = Utf8               com/codename1/ui/Button
  #52 = Class              #51            //  com/codename1/ui/Button
  #53 = Utf8               Test Lambda
  #54 = String             #53            //  Test Lambda
  #55 = Methodref          #52.#49        //  com/codename1/ui/Button."<init>":(Ljava/lang/String;)V
  #56 = Utf8               com/codename1/test/retrolambda/RetroLambdaTest$$Lambda$1
  #57 = Class              #56            //  com/codename1/test/retrolambda/RetroLambdaTest$$Lambda$1
  #58 = Utf8               lambdaFactory$
  #59 = Utf8               ()Lcom/codename1/ui/events/ActionListener;
  #60 = NameAndType        #58:#59        //  lambdaFactory$:()Lcom/codename1/ui/events/ActionListener;
  #61 = Methodref          #57.#60        //  com/codename1/test/retrolambda/RetroLambdaTest$$Lambda$1.lambdaFactory$:()Lcom/codename1/ui/events/ActionListener;
  #62 = Utf8               addActionListener
  #63 = Utf8               (Lcom/codename1/ui/events/ActionListener;)V
  #64 = NameAndType        #62:#63        //  addActionListener:(Lcom/codename1/ui/events/ActionListener;)V
  #65 = Methodref          #52.#64        //  com/codename1/ui/Button.addActionListener:(Lcom/codename1/ui/events/ActionListener;)V
  #66 = Utf8               addComponent
  #67 = Utf8               (Lcom/codename1/ui/Component;)V
  #68 = NameAndType        #66:#67        //  addComponent:(Lcom/codename1/ui/Component;)V
  #69 = Methodref          #27.#68        //  com/codename1/ui/Form.addComponent:(Lcom/codename1/ui/Component;)V
  #70 = Utf8               f
  #71 = Utf8               b
  #72 = Utf8               Lcom/codename1/ui/Button;
  #73 = Utf8               lambda$testLambdas$0
  #74 = Utf8               (Lcom/codename1/ui/events/ActionEvent;)V
  #75 = Utf8               java/lang/System
  #76 = Class              #75            //  java/lang/System
  #77 = Utf8               out
  #78 = Utf8               Ljava/io/PrintStream;
  #79 = NameAndType        #77:#78        //  out:Ljava/io/PrintStream;
  #80 = Fieldref           #76.#79        //  java/lang/System.out:Ljava/io/PrintStream;
  #81 = Utf8               This is a test
  #82 = String             #81            //  This is a test
  #83 = Utf8               java/io/PrintStream
  #84 = Class              #83            //  java/io/PrintStream
  #85 = Utf8               println
  #86 = NameAndType        #85:#48        //  println:(Ljava/lang/String;)V
  #87 = Methodref          #84.#86        //  java/io/PrintStream.println:(Ljava/lang/String;)V
  #88 = Utf8               e
  #89 = Utf8               Lcom/codename1/ui/events/ActionEvent;
  #90 = Utf8               access$lambda$0
  #91 = NameAndType        #73:#74        //  lambda$testLambdas$0:(Lcom/codename1/ui/events/ActionEvent;)V
  #92 = Methodref          #2.#91         //  com/codename1/test/retrolambda/RetroLambdaTest.lambda$testLambdas$0:(Lcom/codename1/ui/events/ActionEvent;)V
  #93 = Utf8               Code
  #94 = Utf8               LocalVariableTable
  #95 = Utf8               LineNumberTable
  #96 = Utf8               SourceFile
  #97 = Utf8               InnerClasses
{
  public com.codename1.test.retrolambda.RetroLambdaTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0       
         1: invokespecial #16                 // Method java/lang/Object."<init>":()V
         4: return        
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/codename1/test/retrolambda/RetroLambdaTest;
      LineNumberTable:
        line 9: 0

  public void init(java.lang.Object);
    descriptor: (Ljava/lang/Object;)V
    flags: ACC_PUBLIC
    Code:
      stack=0, locals=2, args_size=2
         0: return        
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       1     0  this   Lcom/codename1/test/retrolambda/RetroLambdaTest;
            0       1     1 context   Ljava/lang/Object;
      LineNumberTable:
        line 26: 0

  public void start();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0       
         1: getfield      #25                 // Field current:Lcom/codename1/ui/Form;
         4: ifnull        15
         7: aload_0       
         8: getfield      #25                 // Field current:Lcom/codename1/ui/Form;
        11: invokevirtual #30                 // Method com/codename1/ui/Form.show:()V
        14: return        
        15: aload_0       
        16: invokevirtual #33                 // Method testLambdas:()V
        19: return        
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      20     0  this   Lcom/codename1/test/retrolambda/RetroLambdaTest;
      LineNumberTable:
        line 29: 0
        line 30: 7
        line 31: 14
        line 34: 15
        line 35: 19

  public void stop();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0       
         1: invokestatic  #40                 // Method com/codename1/ui/Display.getInstance:()Lcom/codename1/ui/Display;
         4: invokevirtual #44                 // Method com/codename1/ui/Display.getCurrent:()Lcom/codename1/ui/Form;
         7: putfield      #25                 // Field current:Lcom/codename1/ui/Form;
        10: return        
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  this   Lcom/codename1/test/retrolambda/RetroLambdaTest;
      LineNumberTable:
        line 38: 0
        line 39: 10

  public void destroy();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=0, locals=1, args_size=1
         0: return        
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       1     0  this   Lcom/codename1/test/retrolambda/RetroLambdaTest;
      LineNumberTable:
        line 42: 0

  public void testLambdas();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=3, args_size=1
         0: new           #27                 // class com/codename1/ui/Form
         3: dup           
         4: ldc           #47                 // String Lambda Test
         6: invokespecial #50                 // Method com/codename1/ui/Form."<init>":(Ljava/lang/String;)V
         9: astore_1      
        10: new           #52                 // class com/codename1/ui/Button
        13: dup           
        14: ldc           #54                 // String Test Lambda
        16: invokespecial #55                 // Method com/codename1/ui/Button."<init>":(Ljava/lang/String;)V
        19: astore_2      
        20: aload_2       
        21: invokestatic  #61                 // Method com/codename1/test/retrolambda/RetroLambdaTest$$Lambda$1.lambdaFactory$:()Lcom/codename1/ui/events/ActionListener;
        24: invokevirtual #65                 // Method com/codename1/ui/Button.addActionListener:(Lcom/codename1/ui/events/ActionListener;)V
        27: aload_1       
        28: aload_2       
        29: invokevirtual #69                 // Method com/codename1/ui/Form.addComponent:(Lcom/codename1/ui/Component;)V
        32: aload_1       
        33: invokevirtual #30                 // Method com/codename1/ui/Form.show:()V
        36: return        
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      37     0  this   Lcom/codename1/test/retrolambda/RetroLambdaTest;
           10      27     1     f   Lcom/codename1/ui/Form;
           20      17     2     b   Lcom/codename1/ui/Button;
      LineNumberTable:
        line 45: 0
        line 46: 10
        line 47: 20
        line 50: 27
        line 51: 32
        line 52: 36

  static void access$lambda$0(com.codename1.ui.events.ActionEvent);
    descriptor: (Lcom/codename1/ui/events/ActionEvent;)V
    flags: ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0       
         1: invokestatic  #92                 // Method lambda$testLambdas$0:(Lcom/codename1/ui/events/ActionEvent;)V
         4: return        
}
Steves-iMac-2:build8771077083861352612xxx shannah$ 

Here is the retrolambda command used to generate this:

/Library/Java/JavaVirtualMachines/jdk1.8.0_11.jdk/Contents/Home/bin/java -Dretrolambda.inputDir=/var/folders/k7/b5qdhxt88v58wp008k8yxy180000gn/T/build4077814662431771638xxx/Classes -Dretrolambda.classpath=/var/folders/k7/b5qdhxt88v58wp008k8yxy180000gn/T/build4077814662431771638xxx/Classes:/var/folders/k7/b5qdhxt88v58wp008k8yxy180000gn/T/temp8696717259614833472.jar -Dretrolambda.outputDir=/var/folders/k7/b5qdhxt88v58wp008k8yxy180000gn/T/build4077814662431771638xxx/Classes_retrolamda -Dretrolambda.bytecodeVersion=49 -jar /Users/shannah/Downloads/retrolambda-2.0.3.jar Retrolambda 2.0.3
Bytecode version: 49 (Java 5)
Default methods:  false
Input directory:  /var/folders/k7/b5qdhxt88v58wp008k8yxy180000gn/T/build4077814662431771638xxx/Classes
Output directory: /var/folders/k7/b5qdhxt88v58wp008k8yxy180000gn/T/build4077814662431771638xxx/Classes_retrolamda
Classpath:        /var/folders/k7/b5qdhxt88v58wp008k8yxy180000gn/T/build4077814662431771638xxx/Classes:/var/folders/k7/b5qdhxt88v58wp008k8yxy180000gn/T/temp8696717259614833472.jar
Saving lambda class: com/codename1/test/retrolambda/RetroLambdaTest$$Lambda$1

Here is a workaround I'm using to post-process the output. It strips inner classes of types in java.lang.invoke. This is too heavy-handed for the general case, but for my purposes I'm targeting platforms that don't have java.lang.invoke so I can make assumptions that any references to them should be gone.

/**
     * Retrolambda seems to leave class constants for java/lang/invoke classes
     * in the constant pool even though they aren't used.  This will strip 
     * them out.
     * @param classFile
     * @throws IOException 
     */
    private void stripInvokeClassConstants(File classFile) throws IOException {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(classFile);
            ClassReader r = new ClassReader(fis);
            ClassWriter w = new ClassWriter(ClassWriter.COMPUTE_MAXS) {
                @Override
                public void visitInnerClass(String string, String string1, String string2, int i) {
                    if (!string.startsWith("java/lang/invoke")) {
                        super.visitInnerClass(string, string1, string2, i);
                    }
                }



            };
            r.accept(w, 0);
            File out = //new File(classFile.getParentFile(), classFile.getName()+".stripped");
                    classFile;
            createFile(out, w.toByteArray());

        } finally {
            if (fis != null) {
                try { fis.close();} catch(Throwable t){}
            }
        }
    }

This is fixed in Retrolambda 2.0.4

Thanks!

On Wed, Jul 8, 2015 at 10:23 AM, Esko Luontola notifications@github.com
wrote:

This is fixed in Retrolambda 2.0.4


Reply to this email directly or view it on GitHub
#61 (comment)
.

Steve Hannah
Web Lite Solutions Corp.