Skip to content

Commit 2317d92

Browse files
committed
Decide which lambda classes to save based on LambdaReifier's invoker and not the lambda's class loader
Fixes #21
1 parent 663be5d commit 2317d92

File tree

3 files changed

+23
-18
lines changed

3 files changed

+23
-18
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ Version History
152152
- Added an optional `-Dretrolambda.includedFiles` parameter to support the
153153
incremental compilers of build tools
154154
([Issue #23](https://github.com/orfjackal/retrolambda/pull/23))
155+
- Decides which lambda classes to save based on the current class being
156+
processed, instead of the class loader that loaded the lambda class
157+
([Issue #21](https://github.com/orfjackal/retrolambda/issues/21))
155158

156159
### Retrolambda 1.3.0 (2014-06-04)
157160

retrolambda/src/main/java/net/orfjackal/retrolambda/LambdaReifier.java

+14
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public class LambdaReifier {
1919
// be an error if these collections contain more than one element.
2020
private static final BlockingDeque<Handle> currentLambdaImplMethod = new LinkedBlockingDeque<>(1);
2121
private static final BlockingDeque<Handle> currentLambdaBridgeMethod = new LinkedBlockingDeque<>(1);
22+
private static final BlockingDeque<Class<?>> currentInvoker = new LinkedBlockingDeque<>(1);
2223
private static final BlockingDeque<Type> currentInvokedType = new LinkedBlockingDeque<>(1);
2324
private static final BlockingDeque<String> currentLambdaClass = new LinkedBlockingDeque<>(1);
2425

@@ -27,6 +28,7 @@ public static LambdaFactoryMethod reifyLambdaClass(Handle lambdaImplMethod, Hand
2728
try {
2829
setLambdaImplMethod(lambdaImplMethod);
2930
setLambdaBridgeMethod(lambdaBridgeMethod);
31+
setInvoker(invoker);
3032
setInvokedType(invokedType);
3133

3234
// Causes the lambda class to be loaded. Retrolambda's Java agent
@@ -51,6 +53,10 @@ private static void setLambdaBridgeMethod(Handle lambdaBridgeMethod) {
5153
currentLambdaBridgeMethod.push(lambdaBridgeMethod);
5254
}
5355

56+
private static void setInvoker(Class<?> lambdaInvoker) {
57+
currentInvoker.push(lambdaInvoker);
58+
}
59+
5460
private static void setInvokedType(Type invokedType) {
5561
currentInvokedType.push(invokedType);
5662
}
@@ -59,6 +65,13 @@ public static void setLambdaClass(String lambdaClass) {
5965
currentLambdaClass.push(lambdaClass);
6066
}
6167

68+
public static boolean isLambdaClassToReify(String className) {
69+
Class<?> invoker = currentInvoker.peekFirst();
70+
return invoker != null
71+
&& className.startsWith(Type.getInternalName(invoker))
72+
&& LambdaNaming.LAMBDA_CLASS.matcher(className).matches();
73+
}
74+
6275
public static Handle getLambdaImplMethod() {
6376
return currentLambdaImplMethod.getFirst();
6477
}
@@ -76,6 +89,7 @@ public static LambdaFactoryMethod getLambdaFactoryMethod() {
7689
private static void resetGlobals() {
7790
currentLambdaImplMethod.clear();
7891
currentLambdaBridgeMethod.clear();
92+
currentInvoker.clear();
7993
currentInvokedType.clear();
8094
currentLambdaClass.clear();
8195
}

retrolambda/src/main/java/net/orfjackal/retrolambda/LambdaSavingClassFileTransformer.java

+6-18
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,31 @@
99
import java.lang.instrument.*;
1010
import java.nio.file.*;
1111
import java.security.ProtectionDomain;
12-
import java.util.*;
1312

1413
public class LambdaSavingClassFileTransformer implements ClassFileTransformer {
1514

1615
private final Path outputDir;
1716
private final int targetVersion;
18-
private final List<ClassLoader> ignoredClassLoaders = new ArrayList<>();
1917

2018
public LambdaSavingClassFileTransformer(Path outputDir, int targetVersion) {
2119
this.outputDir = outputDir;
2220
this.targetVersion = targetVersion;
23-
for (ClassLoader cl = ClassLoader.getSystemClassLoader(); cl != null; cl = cl.getParent()) {
24-
ignoredClassLoaders.add(cl);
25-
}
26-
ignoredClassLoaders.add(null);
2721
}
2822

2923
@Override
3024
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
31-
if (ignoredClassLoaders.contains(loader)) {
32-
// Avoid saving any classes from the JDK or Retrolambda itself.
33-
// The transformed application classes have their own class loader.
34-
return null;
35-
}
3625
if (className == null) {
3726
// Since JDK 8 build b121 or so, lambda classes have a null class name,
3827
// but we can read it from the bytecode where the name still exists.
3928
className = new ClassReader(classfileBuffer).getClassName();
4029
}
41-
if (!isLambdaClass(className)) {
42-
return null;
30+
if (LambdaReifier.isLambdaClassToReify(className)) {
31+
reifyLambdaClass(className, classfileBuffer);
4332
}
33+
return null;
34+
}
35+
36+
private void reifyLambdaClass(String className, byte[] classfileBuffer) {
4437
try {
4538
System.out.println("Saving lambda class: " + className);
4639
byte[] backportedBytecode = LambdaClassBackporter.transform(classfileBuffer, targetVersion);
@@ -53,10 +46,5 @@ public byte[] transform(ClassLoader loader, String className, Class<?> classBein
5346
System.out.println("ERROR: Failed to backport lambda class: " + className);
5447
t.printStackTrace(System.out);
5548
}
56-
return null;
57-
}
58-
59-
private static boolean isLambdaClass(String className) {
60-
return LambdaNaming.LAMBDA_CLASS.matcher(className).matches();
6149
}
6250
}

0 commit comments

Comments
 (0)