Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.lang.invoke classes left in constant pool #61

Closed
shannah opened this issue Jul 2, 2015 · 3 comments
Closed

java.lang.invoke classes left in constant pool #61

shannah opened this issue Jul 2, 2015 · 3 comments

Comments

@shannah
Copy link

shannah commented Jul 2, 2015

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
@shannah
Copy link
Author

shannah commented Jul 2, 2015

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){}
            }
        }
    }

@luontola
Copy link
Owner

luontola commented Jul 8, 2015

This is fixed in Retrolambda 2.0.4

@shannah
Copy link
Author

shannah commented Jul 8, 2015

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants