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.