diff --git a/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_5.xml b/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_8_1.xml
similarity index 60%
rename from .idea/libraries/Maven__org_apache_commons_commons_lang3_3_5.xml
rename to .idea/libraries/Maven__org_apache_commons_commons_lang3_3_8_1.xml
index 666266cc..33b78e93 100644
--- a/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_5.xml
+++ b/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_8_1.xml
@@ -1,13 +1,13 @@
-
+
-
+
-
+
-
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_ow2_asm_asm_7_0.xml b/.idea/libraries/Maven__org_ow2_asm_asm_7_0.xml
new file mode 100644
index 00000000..085e9d1a
--- /dev/null
+++ b/.idea/libraries/Maven__org_ow2_asm_asm_7_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_ow2_asm_asm_debug_all_5_2.xml b/.idea/libraries/Maven__org_ow2_asm_asm_debug_all_5_2.xml
deleted file mode 100644
index db75e8b0..00000000
--- a/.idea/libraries/Maven__org_ow2_asm_asm_debug_all_5_2.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_ow2_asm_asm_tree_7_0.xml b/.idea/libraries/Maven__org_ow2_asm_asm_tree_7_0.xml
new file mode 100644
index 00000000..03049fed
--- /dev/null
+++ b/.idea/libraries/Maven__org_ow2_asm_asm_tree_7_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/end-to-end-tests/end-to-end-tests.iml b/end-to-end-tests/end-to-end-tests.iml
index 40dc4b05..a3d1fe13 100644
--- a/end-to-end-tests/end-to-end-tests.iml
+++ b/end-to-end-tests/end-to-end-tests.iml
@@ -14,7 +14,8 @@
-
+
+
diff --git a/end-to-end-tests/pom.xml b/end-to-end-tests/pom.xml
index 408f954a..f5d15539 100644
--- a/end-to-end-tests/pom.xml
+++ b/end-to-end-tests/pom.xml
@@ -30,7 +30,13 @@
org.ow2.asm
- asm-debug-all
+ asm
+ test
+
+
+
+ org.ow2.asm
+ asm-tree
test
diff --git a/parent/pom.xml b/parent/pom.xml
index 185e026f..11470df9 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -85,8 +85,14 @@
org.ow2.asm
- asm-debug-all
- 5.2
+ asm
+ 7.0
+
+
+
+ org.ow2.asm
+ asm-tree
+ 7.0
@@ -312,7 +318,7 @@
maven-plugin-plugin
- 3.4
+ 3.6.0
diff --git a/retrolambda-maven-plugin/pom.xml b/retrolambda-maven-plugin/pom.xml
index a3bb1f7d..e1714108 100644
--- a/retrolambda-maven-plugin/pom.xml
+++ b/retrolambda-maven-plugin/pom.xml
@@ -61,7 +61,7 @@
org.apache.commons
commons-lang3
- 3.5
+ 3.8.1
diff --git a/retrolambda-maven-plugin/retrolambda-maven-plugin.iml b/retrolambda-maven-plugin/retrolambda-maven-plugin.iml
index 0ec9480c..7ef880fb 100644
--- a/retrolambda-maven-plugin/retrolambda-maven-plugin.iml
+++ b/retrolambda-maven-plugin/retrolambda-maven-plugin.iml
@@ -13,7 +13,8 @@
-
+
+
@@ -41,7 +42,7 @@
-
+
diff --git a/retrolambda/pom.xml b/retrolambda/pom.xml
index 38a0984f..e44b5fff 100644
--- a/retrolambda/pom.xml
+++ b/retrolambda/pom.xml
@@ -23,7 +23,12 @@
org.ow2.asm
- asm-debug-all
+ asm
+
+
+
+ org.ow2.asm
+ asm-tree
@@ -50,6 +55,7 @@
net.orfjackal.retrolambda.Main
+ true
net.orfjackal.retrolambda.PreMain
diff --git a/retrolambda/retrolambda.iml b/retrolambda/retrolambda.iml
index f58fb626..39d07de4 100644
--- a/retrolambda/retrolambda.iml
+++ b/retrolambda/retrolambda.iml
@@ -11,7 +11,8 @@
-
+
+
diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/Agent.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/Agent.java
new file mode 100644
index 00000000..b963b20a
--- /dev/null
+++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/Agent.java
@@ -0,0 +1,36 @@
+// Copyright © 2013-2018 Esko Luontola and other Retrolambda contributors
+// This software is released under the Apache License 2.0.
+// The license text is at http://www.apache.org/licenses/LICENSE-2.0
+
+package net.orfjackal.retrolambda;
+
+import net.orfjackal.retrolambda.ext.ow2asm.EnhancedClassReader;
+import net.orfjackal.retrolambda.lambdas.LambdaClassSaver;
+import org.objectweb.asm.ClassReader;
+
+public class Agent {
+
+ private static boolean enabled = false;
+ private static LambdaClassSaver lambdaClassSaver;
+ private static boolean isJavacHacksEnabled;
+
+ public static void enable() {
+ enabled = true;
+ }
+
+ public static boolean isEnabled() {
+ return enabled;
+ }
+
+ public static void setLambdaClassSaver(LambdaClassSaver lambdaClassSaver, boolean isJavacHacksEnabled) {
+ Agent.lambdaClassSaver = lambdaClassSaver;
+ Agent.isJavacHacksEnabled = isJavacHacksEnabled;
+ }
+
+ public static void saveLambda(byte[] bytes) {
+ if (lambdaClassSaver != null) {
+ ClassReader reader = EnhancedClassReader.create(bytes, isJavacHacksEnabled);
+ lambdaClassSaver.saveIfLambda(reader.getClassName(), bytes);
+ }
+ }
+}
diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/PreMain.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/PreMain.java
index bd8d228e..62adff9a 100644
--- a/retrolambda/src/main/java/net/orfjackal/retrolambda/PreMain.java
+++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/PreMain.java
@@ -6,23 +6,23 @@
import net.orfjackal.retrolambda.lambdas.*;
+import java.io.File;
import java.lang.instrument.Instrumentation;
+import java.net.URISyntaxException;
+import java.util.jar.JarFile;
public class PreMain {
- private static final LambdaClassSaverAgent agent = new LambdaClassSaverAgent();
- private static boolean agentLoaded = false;
+ public static void premain(String agentArgs, Instrumentation inst) throws Exception {
+ // Append the agent JAR to the bootstrap search path so that the instrumented InnerClassLambdaMetaFactory
+ // could refer to Agent.
+ inst.appendToBootstrapClassLoaderSearch(new JarFile(getAgentJarFile()));
- public static void premain(String agentArgs, Instrumentation inst) {
- inst.addTransformer(agent);
- agentLoaded = true;
+ inst.addTransformer(new InnerClassLambdaMetafactoryTransformer(), true);
+ inst.retransformClasses(Class.forName("java.lang.invoke.InnerClassLambdaMetafactory"));
}
- public static boolean isAgentLoaded() {
- return agentLoaded;
- }
-
- public static void setLambdaClassSaver(LambdaClassSaver lambdaClassSaver, boolean isJavacHacksEnabled) {
- agent.setLambdaClassSaver(lambdaClassSaver, isJavacHacksEnabled);
+ private static File getAgentJarFile() throws URISyntaxException {
+ return new File(PreMain.class.getProtectionDomain().getCodeSource().getLocation().toURI());
}
}
diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/Retrolambda.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/Retrolambda.java
index d6d49579..07d292f0 100644
--- a/retrolambda/src/main/java/net/orfjackal/retrolambda/Retrolambda.java
+++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/Retrolambda.java
@@ -45,7 +45,7 @@ public static void run(Config config) throws Throwable {
Log.info("Classpath: " + classpath);
Log.info("Included files: " + (includedFiles != null ? includedFiles.size() : "all"));
Log.info("JVM version: " + System.getProperty("java.version"));
- Log.info("Agent enabled: " + PreMain.isAgentLoaded());
+ Log.info("Agent enabled: " + Agent.isEnabled());
Log.info("javac hacks: " + isJavacHacksEnabled);
if (!Files.isDirectory(inputDir)) {
@@ -61,8 +61,8 @@ public static void run(Config config) throws Throwable {
LambdaClassSaver lambdaClassSaver = new LambdaClassSaver(outputDirectory, transformers, isJavacHacksEnabled);
try (LambdaClassDumper dumper = new LambdaClassDumper(lambdaClassSaver)) {
- if (PreMain.isAgentLoaded()) {
- PreMain.setLambdaClassSaver(lambdaClassSaver, isJavacHacksEnabled);
+ if (Agent.isEnabled()) {
+ Agent.setLambdaClassSaver(lambdaClassSaver, isJavacHacksEnabled);
} else {
dumper.install();
}
diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/InnerClassLambdaMetafactoryTransformer.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/InnerClassLambdaMetafactoryTransformer.java
new file mode 100644
index 00000000..2697b4c8
--- /dev/null
+++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/InnerClassLambdaMetafactoryTransformer.java
@@ -0,0 +1,61 @@
+// Copyright © 2013-2018 Esko Luontola and other Retrolambda contributors
+// This software is released under the Apache License 2.0.
+// The license text is at http://www.apache.org/licenses/LICENSE-2.0
+
+package net.orfjackal.retrolambda.lambdas;
+
+import com.esotericsoftware.minlog.Log;
+import net.orfjackal.retrolambda.Agent;
+import org.objectweb.asm.*;
+
+import java.lang.instrument.*;
+import java.security.ProtectionDomain;
+
+public class InnerClassLambdaMetafactoryTransformer implements ClassFileTransformer {
+ @Override
+ public byte[] transform(ClassLoader loader, String className, Class> classBeingRedefined, ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {
+ if (!"java/lang/invoke/InnerClassLambdaMetafactory".equals(className)) {
+ return null;
+ }
+
+ try {
+ byte[] transformed = transformMetafactory(bytes);
+ Agent.enable();
+ return transformed;
+ } catch (Throwable e) {
+ Log.error("Failed to transform " + className, e);
+ return null;
+ }
+ }
+
+ private byte[] transformMetafactory(byte[] bytes) {
+ ClassReader cr = new ClassReader(bytes);
+ ClassWriter cw = new ClassWriter(cr, 0);
+ ClassVisitor cv = new ClassVisitor(Opcodes.ASM7, cw) {
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+ MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
+ if (name.equals("spinInnerClass")) {
+ mv = new MethodVisitor(Opcodes.ASM7, mv) {
+ @Override
+ public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
+ if (name.equals("toByteArray")) {
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(Agent.class), "saveLambda", "([B)V", false);
+ }
+ }
+
+ @Override
+ public void visitMaxs(int maxStack, int maxLocals) {
+ super.visitMaxs(maxStack + 1, maxLocals);
+ }
+ };
+ }
+ return mv;
+ }
+ };
+ cr.accept(cv, 0);
+ return cw.toByteArray();
+ }
+}
diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/LambdaClassSaverAgent.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/LambdaClassSaverAgent.java
deleted file mode 100644
index d08a3d1c..00000000
--- a/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/LambdaClassSaverAgent.java
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright © 2013-2018 Esko Luontola and other Retrolambda contributors
-// This software is released under the Apache License 2.0.
-// The license text is at http://www.apache.org/licenses/LICENSE-2.0
-
-package net.orfjackal.retrolambda.lambdas;
-
-import net.orfjackal.retrolambda.ext.ow2asm.EnhancedClassReader;
-
-import java.lang.instrument.*;
-import java.security.ProtectionDomain;
-
-public class LambdaClassSaverAgent implements ClassFileTransformer {
-
- private LambdaClassSaver lambdaClassSaver;
- private boolean isJavacHacksEnabled;
-
- public void setLambdaClassSaver(LambdaClassSaver lambdaClassSaver, boolean isJavacHacksEnabled) {
- this.lambdaClassSaver = lambdaClassSaver;
- this.isJavacHacksEnabled = isJavacHacksEnabled;
- }
-
- @Override
- public byte[] transform(ClassLoader loader, String className, Class> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
- if (className == null) {
- // Since JDK 8 build b121 or so, lambda classes have a null class name,
- // but we can read it from the bytecode where the name still exists.
- className = EnhancedClassReader.create(classfileBuffer, isJavacHacksEnabled).getClassName();
- }
- if (lambdaClassSaver != null) {
- lambdaClassSaver.saveIfLambda(className, classfileBuffer);
- }
- return null;
- }
-}