Skip to content

Commit d6985da

Browse files
committed
Do not generate accessor method for non-private methods.
1 parent 365b819 commit d6985da

File tree

9 files changed

+85
-57
lines changed

9 files changed

+85
-57
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static void run(Config config) throws Throwable {
3838

3939
Thread.currentThread().setContextClassLoader(new NonDelegatingClassLoader(asUrls(classpath)));
4040

41-
ClassHierarchyAnalyzer analyzer = new ClassHierarchyAnalyzer();
41+
ClassAnalyzer analyzer = new ClassAnalyzer();
4242
OutputDirectory outputDirectory = new OutputDirectory(outputDir);
4343
Transformers transformers = new Transformers(bytecodeVersion, defaultMethodsEnabled, analyzer);
4444
LambdaClassSaver lambdaClassSaver = new LambdaClassSaver(outputDirectory, transformers);

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ public class Transformers {
1717

1818
private final int targetVersion;
1919
private final boolean defaultMethodsEnabled;
20-
private final ClassHierarchyAnalyzer analyzer;
20+
private final ClassAnalyzer analyzer;
2121

22-
public Transformers(int targetVersion, boolean defaultMethodsEnabled, ClassHierarchyAnalyzer analyzer) {
22+
public Transformers(int targetVersion, boolean defaultMethodsEnabled, ClassAnalyzer analyzer) {
2323
this.targetVersion = targetVersion;
2424
this.defaultMethodsEnabled = defaultMethodsEnabled;
2525
this.analyzer = analyzer;
@@ -48,7 +48,7 @@ public byte[] backportClass(ClassReader reader) {
4848
next = new UpdateRelocatedMethodInvocations(next, analyzer);
4949
next = new AddMethodDefaultImplementations(next, analyzer);
5050
}
51-
next = new BackportLambdaInvocations(next);
51+
next = new BackportLambdaInvocations(next, analyzer);
5252
return next;
5353
});
5454
}
@@ -59,7 +59,7 @@ public List<byte[]> backportInterface(ClassReader reader) {
5959
// the wrong one of them is written to disk last.
6060
ClassNode lambdasBackported = new ClassNode();
6161
ClassVisitor next = lambdasBackported;
62-
next = new BackportLambdaInvocations(next);
62+
next = new BackportLambdaInvocations(next, analyzer);
6363
reader.accept(next, 0);
6464

6565
List<byte[]> results = new ArrayList<>();

retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/AddMethodDefaultImplementations.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111

1212
public class AddMethodDefaultImplementations extends ClassVisitor {
1313

14-
private final ClassHierarchyAnalyzer analyzer;
14+
private final ClassAnalyzer analyzer;
1515
private String className;
1616

17-
public AddMethodDefaultImplementations(ClassVisitor next, ClassHierarchyAnalyzer analyzer) {
17+
public AddMethodDefaultImplementations(ClassVisitor next, ClassAnalyzer analyzer) {
1818
super(ASM5, next);
1919
this.analyzer = analyzer;
2020
}

retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassHierarchyAnalyzer.java renamed to retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassAnalyzer.java

+12-6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import static net.orfjackal.retrolambda.util.Flags.*;
1515
import static org.objectweb.asm.Opcodes.*;
1616

17-
public class ClassHierarchyAnalyzer {
17+
public class ClassAnalyzer {
1818

1919
private final Map<Type, ClassInfo> classes = new HashMap<>();
2020
private final Map<MethodRef, MethodRef> relocatedMethods = new HashMap<>();
@@ -45,10 +45,16 @@ public void visit(int version, int access, String name, String signature, String
4545

4646
@Override
4747
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
48-
if (isConstructor(name) || isStaticMethod(access)) {
49-
return null;
48+
int tag;
49+
if (isConstructor(name)) {
50+
tag = H_INVOKESPECIAL;
51+
} else if (isStaticMethod(access)) {
52+
tag = H_INVOKESTATIC;
53+
} else {
54+
tag = H_INVOKEVIRTUAL;
5055
}
51-
c.addMethod(new MethodRef(H_INVOKEVIRTUAL, owner, name, desc), new MethodKind.Implemented());
56+
57+
c.addMethod(access, new MethodRef(tag, owner, name, desc), new MethodKind.Implemented());
5258
return null;
5359
}
5460

@@ -71,12 +77,12 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si
7177
MethodRef method = new MethodRef(Handles.accessToTag(access, true), owner, name, desc);
7278

7379
if (isAbstractMethod(access)) {
74-
c.addMethod(method, new MethodKind.Abstract());
80+
c.addMethod(access, method, new MethodKind.Abstract());
7581

7682
} else if (isDefaultMethod(access)) {
7783
MethodRef defaultImpl = new MethodRef(H_INVOKESTATIC, companion, name, Bytecode.prependArgumentType(desc, Type.getObjectType(owner)));
7884
c.enableCompanionClass();
79-
c.addMethod(method, new MethodKind.Default(defaultImpl));
85+
c.addMethod(access, method, new MethodKind.Default(defaultImpl));
8086

8187
} else if (isInstanceLambdaImplMethod(access)) {
8288
relocatedMethods.put(method, new MethodRef(H_INVOKESTATIC, companion, name, Bytecode.prependArgumentType(desc, Type.getObjectType(owner))));

retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassInfo.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ public List<MethodInfo> getMethods() {
4444
return Collections.unmodifiableList(methods);
4545
}
4646

47-
public void addMethod(MethodRef method, MethodKind kind) {
48-
methods.add(new MethodInfo(method.tag, method.getSignature(), Type.getObjectType(method.owner), kind));
47+
public void addMethod(int access, MethodRef method, MethodKind kind) {
48+
methods.add(new MethodInfo(access, method.tag, method.getSignature(), Type.getObjectType(method.owner), kind));
4949
}
5050

5151
public Optional<Type> getCompanionClass() {

retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/MethodInfo.java

+7-4
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,19 @@
1111

1212
public class MethodInfo {
1313

14+
public final int access;
1415
public final int tag;
1516
public final MethodSignature signature;
1617
public final Type owner;
1718
public final MethodKind kind;
1819

19-
public MethodInfo(String name, String desc, Class<?> owner, MethodKind kind) { // only for tests, so we can ignore the tag
20-
this(-1, new MethodSignature(name, desc), Type.getType(owner), kind);
20+
public MethodInfo(String name, String desc, Class<?> owner, MethodKind kind) {
21+
// only for tests, so we can ignore the tag and access
22+
this(0, -1, new MethodSignature(name, desc), Type.getType(owner), kind);
2123
}
2224

23-
public MethodInfo(int tag, MethodSignature signature, Type owner, MethodKind kind) {
25+
public MethodInfo(int access, int tag, MethodSignature signature, Type owner, MethodKind kind) {
26+
this.access = access;
2427
this.tag = tag;
2528
this.signature = signature;
2629
this.owner = owner;
@@ -58,7 +61,7 @@ public String toString() {
5861
.addValue(signature)
5962
.addValue(owner)
6063
.addValue(kind)
61-
.addValue("(" + tag + ")")
64+
.addValue("(tag=" + tag + ", access=" + access + ")")
6265
.toString();
6366
}
6467
}

retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/UpdateRelocatedMethodInvocations.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111

1212
public class UpdateRelocatedMethodInvocations extends ClassVisitor {
1313

14-
private final ClassHierarchyAnalyzer analyzer;
14+
private final ClassAnalyzer analyzer;
1515

16-
public UpdateRelocatedMethodInvocations(ClassVisitor next, ClassHierarchyAnalyzer analyzer) {
16+
public UpdateRelocatedMethodInvocations(ClassVisitor next, ClassAnalyzer analyzer) {
1717
super(ASM5, next);
1818
this.analyzer = analyzer;
1919
}

retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/BackportLambdaInvocations.java

+21-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
package net.orfjackal.retrolambda.lambdas;
66

7+
import net.orfjackal.retrolambda.interfaces.*;
78
import net.orfjackal.retrolambda.util.Bytecode;
89
import org.objectweb.asm.*;
910

@@ -18,10 +19,12 @@ public class BackportLambdaInvocations extends ClassVisitor {
1819

1920
private int classAccess;
2021
private String className;
22+
private final ClassAnalyzer analyzer;
2123
private final Map<Handle, Handle> lambdaAccessToImplMethods = new LinkedHashMap<>();
2224

23-
public BackportLambdaInvocations(ClassVisitor next) {
25+
public BackportLambdaInvocations(ClassVisitor next, ClassAnalyzer analyzer) {
2426
super(ASM5, next);
27+
this.analyzer = analyzer;
2528
}
2629

2730
@Override
@@ -62,14 +65,30 @@ Handle getLambdaAccessMethod(Handle implMethod) {
6265
// the method will be relocated to a companion class
6366
return implMethod;
6467
}
65-
// TODO: do not generate an access method if the impl method is not private (probably not implementable with a single pass)
68+
if (isOwnedMethodVisible(implMethod)) {
69+
// The method is visible to the companion class and therefore doesn't need an accessor.
70+
return implMethod;
71+
}
6672
String name = "access$lambda$" + lambdaAccessToImplMethods.size();
6773
String desc = getLambdaAccessMethodDesc(implMethod);
6874
Handle accessMethod = new Handle(H_INVOKESTATIC, className, name, desc);
6975
lambdaAccessToImplMethods.put(accessMethod, implMethod);
7076
return accessMethod;
7177
}
7278

79+
private boolean isOwnedMethodVisible(Handle implMethod) {
80+
MethodSignature implSignature = new MethodSignature(implMethod.getName(), implMethod.getDesc());
81+
82+
Collection<MethodInfo> methods = analyzer.getMethods(Type.getObjectType(implMethod.getOwner()));
83+
for (MethodInfo method : methods) {
84+
if (method.signature.equals(implSignature)) {
85+
// The method will be visible to the companion class if the private flag is absent.
86+
return (method.access & ACC_PRIVATE) == 0;
87+
}
88+
}
89+
throw new IllegalStateException("Non-analyzed method " + implMethod + ". Report this as a bug.");
90+
}
91+
7392
private String getLambdaAccessMethodDesc(Handle implMethod) {
7493
if (implMethod.getTag() == H_INVOKESTATIC) {
7594
// static method call -> keep as-is

0 commit comments

Comments
 (0)