Skip to content

Commit 485b664

Browse files
committed
Fixes #238: Classes with multiple intersecting interfaces are confusing the stackmap frame generator
1 parent fb2fbf1 commit 485b664

16 files changed

+65
-50
lines changed

src/share/classes/com/sun/btrace/runtime/BTraceClassReader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public String[] readClassSupers() {
134134
}
135135

136136
public boolean isInterface() {
137-
return (getAccess() & Opcodes.ACC_STATIC) != 0;
137+
return (getAccess() & Opcodes.ACC_INTERFACE) != 0;
138138
}
139139

140140
public boolean isBTrace() {

src/share/classes/com/sun/btrace/runtime/BTraceClassWriter.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,12 @@ protected String getCommonSuperClass(String type1, String type2) {
8686
InstrumentUtils.collectHierarchyClosure(targetCL, type2, type2Closure, true);
8787
// basically, do intersection
8888
type1Closure.retainAll(type2Closure);
89+
8990
// if the intersection is not empty the first element is the closest common ancestor
9091
Iterator<String> iter = type1Closure.iterator();
9192
if (iter.hasNext()) {
92-
return iter.next();
93+
String common = iter.next();
94+
return common;
9395
}
9496
return Constants.JAVA_LANG_OBJECT;
9597
}

src/share/classes/com/sun/btrace/runtime/ClassFilter.java

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525
package com.sun.btrace.runtime;
2626

27+
import com.sun.btrace.DebugSupport;
2728
import java.lang.annotation.Annotation;
2829
import java.util.ArrayList;
2930
import java.util.List;
@@ -35,11 +36,7 @@
3536
import com.sun.btrace.org.objectweb.asm.MethodVisitor;
3637
import com.sun.btrace.annotations.BTrace;
3738
import java.lang.ref.Reference;
38-
import java.util.Arrays;
39-
import java.util.Collection;
40-
import java.util.HashSet;
41-
import java.util.LinkedHashSet;
42-
import java.util.Set;
39+
import java.util.*;
4340
import java.util.regex.PatternSyntaxException;
4441

4542
/**
@@ -232,7 +229,7 @@ public static boolean isSubTypeOf(Class clazz, String typeName) {
232229
* @param types any requested supertypes
233230
**/
234231
public static boolean isSubTypeOf(String typeA, ClassLoader loader, String ... types) {
235-
if (typeA == null) {
232+
if (typeA == null || typeA.equals(Constants.JAVA_LANG_OBJECT)) {
236233
return false;
237234
}
238235
if (types.length == 0) {
@@ -243,16 +240,23 @@ public static boolean isSubTypeOf(String typeA, ClassLoader loader, String ... t
243240

244241
loader = (loader != null ? loader : ClassLoader.getSystemClassLoader());
245242

243+
if (internal) {
244+
typeA = typeA.replace('.', '/');
245+
} else {
246+
typeA = typeA.replace('/', '.');
247+
}
248+
246249
Set<String> typeSet = new HashSet<>(Arrays.asList(types));
247250
if (typeSet.contains(typeA)) {
248251
return true;
249252
}
250-
251-
LinkedHashSet<String> closure = new LinkedHashSet<>();
252-
InstrumentUtils.collectHierarchyClosure(loader, typeA, closure, internal);
253-
254-
closure.retainAll(typeSet);
255-
return !closure.isEmpty();
253+
ClassInfo ci = ClassCache.getInstance().get(loader, typeA);
254+
Collection<String> sTypes = new LinkedList<>();
255+
for (ClassInfo sCi : ci.getSupertypes(false)) {
256+
sTypes.add(internal ? sCi.getClassName() : sCi.getJavaClassName());
257+
}
258+
sTypes.retainAll(typeSet);
259+
return !sTypes.isEmpty();
256260
}
257261

258262
/*

src/share/classes/com/sun/btrace/runtime/ClassInfo.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public final class ClassInfo {
4747
private final String classId;
4848
private final Collection<ClassInfo> supertypes = new LinkedList<>();
4949
private final ClassCache cache;
50+
private boolean isInterface = false;
5051

5152
ClassInfo(ClassCache cache, Class clz) {
5253
this.cache = cache;
@@ -62,13 +63,14 @@ public final class ClassInfo {
6263
supertypes.add(cache.get(itfc));
6364
}
6465
}
66+
this.isInterface = clz.isInterface();
6567
}
6668

6769
ClassInfo(ClassCache cache, ClassLoader cl, String className) {
6870
this.cache = cache;
6971
cLoaderId = (cl != null ? cl.toString() : "<null>");
7072
classId = className.replace("/", ".");
71-
supertypes.addAll(resolveSupertypes(cl, className));
73+
loadExternalClass(cl, className);
7274
}
7375

7476
/**
@@ -108,31 +110,35 @@ public String getJavaClassName() {
108110
return classId;
109111
}
110112

111-
private Collection<ClassInfo> resolveSupertypes(final ClassLoader cl, final String className) {
112-
final Collection<ClassInfo> supers = new LinkedList<>();
113+
public boolean isInterface() {
114+
return isInterface;
115+
}
116+
117+
private void loadExternalClass(final ClassLoader cl, final String className) {
113118
String rsrcName = className.replace(".", "/") + ".class";
114119
InputStream typeIs = cl == null ? SYS_CL.getResourceAsStream(rsrcName) : cl.getResourceAsStream(rsrcName);
115120
if (typeIs != null) {
116121
try {
117122
BTraceClassReader cr = new BTraceClassReader(cl, typeIs);
123+
124+
this.isInterface = cr.isInterface();
118125
String[] info = cr.readClassSupers();
119126
String superName = info[0];
120127
if (superName != null) {
121-
supers.add(cache.get(inferClassLoader(cl, superName), superName));
128+
supertypes.add(cache.get(inferClassLoader(cl, superName), superName));
122129
}
123130
if (info.length > 1) {
124131
for(int i = 1; i < info.length; i++) {
125132
String ifc = info[i];
126133
if (ifc != null) {
127-
supers.add(cache.get(inferClassLoader(cl, ifc), ifc));
134+
supertypes.add(cache.get(inferClassLoader(cl, ifc), ifc));
128135
}
129136
}
130137
}
131138
} catch (IOException e) {
132139
DebugSupport.warning(e);
133140
}
134141
}
135-
return supers;
136142
}
137143

138144
private static ClassLoader inferClassLoader(ClassLoader initiating, String className) {
@@ -207,10 +213,12 @@ public boolean equals(Object obj) {
207213
if (!Objects.equals(this.cLoaderId, other.cLoaderId)) {
208214
return false;
209215
}
210-
if (!Objects.equals(this.classId, other.classId)) {
211-
return false;
212-
}
213-
return true;
216+
return Objects.equals(this.classId, other.classId);
217+
}
218+
219+
@Override
220+
public String toString() {
221+
return "ClassInfo{" + "cLoaderId=" + cLoaderId + ", classId=" + classId + ", supertypes=" + supertypes + '}';
214222
}
215223

216224
}

src/share/classes/com/sun/btrace/runtime/InstrumentUtils.java

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.io.IOException;
3434
import java.io.InputStream;
3535
import java.util.LinkedHashSet;
36+
import java.util.Set;
3637

3738
/**
3839
* @author A. Sundararajan
@@ -49,12 +50,23 @@ public final class InstrumentUtils {
4950
* @param useInternal should internal types names be used in the closure
5051
*/
5152
public static void collectHierarchyClosure(ClassLoader cl, String type,
52-
LinkedHashSet<String> closure, boolean useInternal) {
53+
Set<String> closure, boolean useInternal) {
5354
if (type == null || type.equals(JAVA_LANG_OBJECT)) {
5455
return;
5556
}
5657
ClassInfo ci = ClassCache.getInstance().get(cl, type);
58+
59+
Set<ClassInfo> ciSet = new LinkedHashSet<>();
60+
61+
// add self
62+
ciSet.add(ci);
5763
for(ClassInfo sci : ci.getSupertypes(false)) {
64+
if (!sci.isInterface() && !sci.getClassName().equals(JAVA_LANG_OBJECT)) {
65+
ciSet.add(sci);
66+
}
67+
}
68+
69+
for (ClassInfo sci : ciSet) {
5870
closure.add(useInternal ? sci.getClassName() : sci.getJavaClassName());
5971
}
6072
}
@@ -82,18 +94,6 @@ public static String arrayDescriptorFor(int typeCode) {
8294
}
8395
}
8496

85-
public static byte[] instrument(byte[] code, BTraceProbe probe) {
86-
BTraceClassReader cr = newClassReader(code);
87-
ClassWriter cw = newClassWriter(cr);
88-
89-
ClassVisitor instr = Instrumentor.create(cr, probe, cw);
90-
if (instr != null) {
91-
accept(cr, instr);
92-
return cw.toByteArray();
93-
}
94-
return code;
95-
}
96-
9797
public static void accept(ClassReader reader, ClassVisitor visitor) {
9898
accept(reader, visitor, ClassReader.SKIP_FRAMES);
9999
}
@@ -131,7 +131,7 @@ public static ClassWriter newClassWriter() {
131131
return newClassWriter(null, ClassWriter.COMPUTE_FRAMES);
132132
}
133133

134-
static BTraceClassWriter newClassWriter(ClassLoader cl, String className, byte[] code) {
134+
static BTraceClassWriter newClassWriter(ClassLoader cl, byte[] code) {
135135
int flags = ClassWriter.COMPUTE_MAXS;
136136
if (isJDK16OrAbove(code)) {
137137
flags = ClassWriter.COMPUTE_FRAMES;

src/share/classes/com/sun/btrace/runtime/Instrumentor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ public class Instrumentor extends ClassVisitor {
7878
private final ClassLoader loader;
7979

8080
static Instrumentor create(BTraceClassReader cr, BTraceProbe bcn, ClassVisitor cv) {
81+
if (cr.isInterface()) {
82+
// do not instrument interfaces
83+
return null;
84+
}
85+
8186
Collection<OnMethod> applicables = bcn.getApplicableHandlers(cr);
8287
if (applicables != null && !applicables.isEmpty()) {
8388
return new Instrumentor(cr.getClassLoader(), bcn, applicables, cv);

src/test/com/sun/btrace/runtime/BTRACE106Test.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
package com.sun.btrace.runtime;
2727

28-
import support.InstrumentorTestBase;
2928
import org.junit.Test;
3029

3130
/**

src/test/com/sun/btrace/runtime/BTRACE189Test.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
package com.sun.btrace.runtime;
2727

28-
import support.InstrumentorTestBase;
2928
import org.junit.Test;
3029

3130
/**

src/test/com/sun/btrace/runtime/BTRACE22Test.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
package com.sun.btrace.runtime;
2727

28-
import support.InstrumentorTestBase;
2928
import org.junit.Test;
3029

3130
/**

src/test/com/sun/btrace/runtime/BTRACE28Test.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
package com.sun.btrace.runtime;
2727

28-
import support.InstrumentorTestBase;
2928
import org.junit.Test;
3029

3130
/**

0 commit comments

Comments
 (0)