From 4d6518ddc92fd5e1b8ab011e394e8b18a7cb9dd6 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Sun, 18 Oct 2020 14:10:49 +0200 Subject: [PATCH 1/3] Don't process default methods at all --- .../orfjackal/retrolambda/ClassAnalyzer.java | 20 +++++++++++++------ .../retrolambda/interfaces/ClassInfo.java | 4 ++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/ClassAnalyzer.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/ClassAnalyzer.java index 17cfd719..0a019a7e 100644 --- a/retrolambda/src/main/java/net/orfjackal/retrolambda/ClassAnalyzer.java +++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/ClassAnalyzer.java @@ -22,6 +22,10 @@ public class ClassAnalyzer { private final Map relocatedMethods = new HashMap<>(); private final Map renamedLambdaMethods = new HashMap<>(); + protected String companionClassName(String name) { + return name + "$"; + } + public void analyze(byte[] bytecode, boolean isJavacHacksEnabled) { analyze(EnhancedClassReader.create(bytecode, isJavacHacksEnabled)); } @@ -68,12 +72,14 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si private void analyzeInterface(ClassInfo c, ClassReader cr) { cr.accept(new ClassVisitor(ASM5) { private String owner; - private String companion; @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { this.owner = name; - this.companion = name + "$"; + } + + private String companionName() { + return companionClassName(owner); } @Override @@ -84,17 +90,19 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si c.addMethod(access, method, new MethodKind.Abstract()); } else if (isDefaultMethod(access)) { + String companion = companionName(); MethodRef defaultImpl = new MethodRef(H_INVOKESTATIC, companion, name, Bytecode.prependArgumentType(desc, Type.getObjectType(owner))); - c.enableCompanionClass(); + c.enableCompanionClass(companion); c.addMethod(access, method, new MethodKind.Default(defaultImpl)); } else if (isInstanceLambdaImplMethod(access)) { + String companion = companionName(); relocatedMethods.put(method, new MethodRef(H_INVOKESTATIC, companion, name, Bytecode.prependArgumentType(desc, Type.getObjectType(owner)))); - c.enableCompanionClass(); - + c.enableCompanionClass(companion); } else if (isStaticMethod(access) && !isStaticInitializer(name, desc, access)) { + String companion = companionName(); relocatedMethods.put(method, new MethodRef(H_INVOKESTATIC, companion, name, desc)); - c.enableCompanionClass(); + c.enableCompanionClass(companion); } return null; } diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassInfo.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassInfo.java index 2f969058..99405a2a 100644 --- a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassInfo.java +++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassInfo.java @@ -52,8 +52,8 @@ public Optional getCompanionClass() { return companionClass; } - public void enableCompanionClass() { - this.companionClass = Optional.of(Type.getObjectType(type.getInternalName() + "$")); + public void enableCompanionClass(String name) { + this.companionClass = Optional.of(Type.getObjectType(name)); } public boolean isClass() { From 03868c59e94960dcaff2ba79b7012309ccc8648a Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Sun, 1 Nov 2020 08:25:44 +0100 Subject: [PATCH 2/3] Allow reification of java.util.function.Function interface --- .../retrolambda/lambdas/LambdaReifier.java | 4 +- .../orfjackal/retrolambda/lambdas/Types.java | 3 +- .../orfjackal/retrolambda/FunctionTest.java | 58 +++++++++++++++++++ 3 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 retrolambda/src/test/java/net/orfjackal/retrolambda/FunctionTest.java diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/LambdaReifier.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/LambdaReifier.java index f8473d76..5e05abb0 100644 --- a/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/LambdaReifier.java +++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/LambdaReifier.java @@ -122,8 +122,8 @@ private static CallSite callBootstrapMethod(Class invoker, String invokedName } private static MethodHandles.Lookup getLookup(Class targetClass) throws Exception { - Constructor ctor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class); + Constructor ctor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class); ctor.setAccessible(true); - return ctor.newInstance(targetClass); + return ctor.newInstance(targetClass, 0x1f); } } diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Types.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Types.java index fe9e0cea..ce35aa5a 100644 --- a/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Types.java +++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Types.java @@ -40,7 +40,8 @@ private static Class toClass(Type type, ClassLoader classLoader) throws Class public static MethodHandle toMethodHandle(Handle handle, ClassLoader classLoader, MethodHandles.Lookup lookup) throws Exception { MethodType type = MethodType.fromMethodDescriptorString(handle.getDesc(), classLoader); Class owner = classLoader.loadClass(handle.getOwner().replace('/', '.')); - + final String className = handle.getOwner().replace('/', '.'); + Class owner = Class.forName(className, false, classLoader); switch (handle.getTag()) { case H_INVOKESTATIC: return lookup.findStatic(owner, handle.getName(), type); diff --git a/retrolambda/src/test/java/net/orfjackal/retrolambda/FunctionTest.java b/retrolambda/src/test/java/net/orfjackal/retrolambda/FunctionTest.java new file mode 100644 index 00000000..85af4ea5 --- /dev/null +++ b/retrolambda/src/test/java/net/orfjackal/retrolambda/FunctionTest.java @@ -0,0 +1,58 @@ +// Copyright © 2013-2017 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 java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.function.Function; +import org.junit.Assert; +import static org.junit.Assert.assertNotNull; +import org.junit.Test; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.Opcodes; + +public class FunctionTest { + @Test + public void convertFunction() throws Throwable { + InputStream is = Function.class.getResourceAsStream("Function.class"); + assertNotNull("Bytecode of Function found", is); + + byte[] oldB = readFully(is); + + ClassAnalyzer analyzer = new ClassAnalyzer(); + Transformers transformers = new Transformers(Opcodes.V1_7, true, analyzer); + try { + byte[] newB = transformers.backportClass(new ClassReader(oldB)); + assertNotNull("No exception", newB); + Assert.assertNotEquals("Different", oldB, newB); + } catch (RuntimeException ex) { + Throwable t = ex; + while (t != null) { + if (t instanceof IllegalArgumentException) { + throw t; + } + t = t.getCause(); + } + } + } + + static byte[] readFully(InputStream is) throws IOException { + if (is == null) { + throw new IOException(); + } + byte[] arr = new byte[4096 * 4096]; + int off = 0; + for (;;) { + int len = is.read(arr, off, arr.length - off); + if (len == -1) { + break; + } + off += len; + } + return Arrays.copyOf(arr, off); + } +} + From 5b883f5024ac7d59905289151c96a9767c3a6169 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Fri, 9 Jul 2021 07:54:38 +0200 Subject: [PATCH 3/3] One definition of owner is enough --- .../src/main/java/net/orfjackal/retrolambda/lambdas/Types.java | 1 - 1 file changed, 1 deletion(-) diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Types.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Types.java index ce35aa5a..f1259189 100644 --- a/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Types.java +++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Types.java @@ -39,7 +39,6 @@ private static Class toClass(Type type, ClassLoader classLoader) throws Class public static MethodHandle toMethodHandle(Handle handle, ClassLoader classLoader, MethodHandles.Lookup lookup) throws Exception { MethodType type = MethodType.fromMethodDescriptorString(handle.getDesc(), classLoader); - Class owner = classLoader.loadClass(handle.getOwner().replace('/', '.')); final String className = handle.getOwner().replace('/', '.'); Class owner = Class.forName(className, false, classLoader); switch (handle.getTag()) {