Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix class loader issues in instrumentation tests.

The ASM ClassWriter uses a wimpy class loader when computing common
superclasses. This could cause a ClassNotFoundException in the
transform method (at reader.accept). This exception gets swallowed,
resulting in a class that should be instrumented to silently not
be. The fix is to override getCommonSuperClass to use the correct
class loader.

Trivia: This bug was discovered while 'stress-testing' this
instrumentation scheme on the Coursera students, to check that they
implement one method in terms of another in the assignment.
  • Loading branch information...
commit f2e45fccfe53ff79ae34f9ca6cae1afa0d153e53 1 parent 6fd9277
Nada Amin namin authored paulp committed
Showing with 28 additions and 2 deletions.
  1. +28 −2 src/partest/scala/tools/partest/javaagent/ASMTransformer.java
30 src/partest/scala/tools/partest/javaagent/ASMTransformer.java
View
@@ -26,9 +26,35 @@ private boolean shouldTransform(String className) {
className.startsWith("instrumented/"));
}
- public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
+ public byte[] transform(final ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
if (shouldTransform(className)) {
- ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
+ // this is copied verbatim from the superclass,
+ // except that we use the outer class loader
+ @Override protected String getCommonSuperClass(final String type1, final String type2) {
+ Class<?> c, d;
+ try {
+ c = Class.forName(type1.replace('/', '.'), false, classLoader);
+ d = Class.forName(type2.replace('/', '.'), false, classLoader);
+ } catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ if (c.isAssignableFrom(d)) {
+ return type1;
+ }
+ if (d.isAssignableFrom(c)) {
+ return type2;
+ }
+ if (c.isInterface() || d.isInterface()) {
+ return "java/lang/Object";
+ } else {
+ do {
+ c = c.getSuperclass();
+ } while (!c.isAssignableFrom(d));
+ return c.getName().replace('.', '/');
+ }
+ }
+ };
ProfilerVisitor visitor = new ProfilerVisitor(writer);
ClassReader reader = new ClassReader(classfileBuffer);
reader.accept(visitor, 0);
Please sign in to comment.
Something went wrong with that request. Please try again.