From f8e066dacc3176561610ba0faaedc89f08f27e55 Mon Sep 17 00:00:00 2001 From: Dmitry Tsitelov <cit@devexperts.com> Date: Fri, 1 Sep 2017 21:33:13 +0300 Subject: [PATCH] Fix: don't track <init> invocations to avoid verification errors --- .../devexperts/aprof/transformer/AProfTransformer.java | 10 ++++++---- .../aprof/transformer/AbstractMethodVisitor.java | 6 ++++-- .../java/com/devexperts/aprof/transformer/Context.java | 6 +++++- .../devexperts/aprof/transformer/MethodAnalyzer.java | 4 ++-- .../aprof/transformer/MethodTransformer.java | 4 ++-- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/transformer/src/main/java/com/devexperts/aprof/transformer/AProfTransformer.java b/transformer/src/main/java/com/devexperts/aprof/transformer/AProfTransformer.java index bae45ea..5a92b8a 100644 --- a/transformer/src/main/java/com/devexperts/aprof/transformer/AProfTransformer.java +++ b/transformer/src/main/java/com/devexperts/aprof/transformer/AProfTransformer.java @@ -133,7 +133,7 @@ private byte[] transformImpl(ClassLoader loader, String internalClassName, ClassWriter cw = computeFrames ? new FrameClassWriter(cr, loader) : new ClassWriter(ClassWriter.COMPUTE_MAXS); - ClassVisitor classTransformer = new ClassTransformer(cw, classAnalyzer.contexts); + ClassVisitor classTransformer = new ClassTransformer(cw, classAnalyzer.contexts, classAnalyzer.classVersion); int transformFlags = (config.isSkipDebug() ? ClassReader.SKIP_DEBUG : 0) + (config.isNoFrames() || computeFrames ? ClassReader.SKIP_FRAMES : 0); @@ -255,16 +255,18 @@ public MethodVisitor visitMethod(final int access, final String mname, final Str } Context context = new Context(config, ciCache, loader, binaryClassName, cname, mname, desc); contexts.add(context); - return new MethodAnalyzer(new GeneratorAdapter(new EmptyMethodVisitor(), access, mname, desc), context); + return new MethodAnalyzer(new GeneratorAdapter(new EmptyMethodVisitor(), access, mname, desc), context, classVersion); } } private class ClassTransformer extends ClassVisitor { private final Iterator<Context> contextIterator; + private final int classVersion; - public ClassTransformer(ClassVisitor cv, List<Context> contexts) { + public ClassTransformer(ClassVisitor cv, List<Context> contexts, int classVersion) { super(TransformerUtil.ASM_API, cv); this.contextIterator = contexts.iterator(); + this.classVersion = classVersion; } @Override @@ -281,7 +283,7 @@ public MethodVisitor visitMethod(final int access, final String mname, final Str MethodVisitor visitor = super.visitMethod(access, mname, desc, signature, exceptions); visitor = new TryCatchBlockSorter(visitor, access, mname, desc, signature, exceptions); Context context = contextIterator.next(); - visitor = new MethodTransformer(new GeneratorAdapter(visitor, access, mname, desc), context); + visitor = new MethodTransformer(new GeneratorAdapter(visitor, access, mname, desc), context, classVersion); visitor = new JSRInlinerAdapter(visitor, access, mname, desc, signature, exceptions); return visitor; } diff --git a/transformer/src/main/java/com/devexperts/aprof/transformer/AbstractMethodVisitor.java b/transformer/src/main/java/com/devexperts/aprof/transformer/AbstractMethodVisitor.java index d409f24..1b0aa06 100644 --- a/transformer/src/main/java/com/devexperts/aprof/transformer/AbstractMethodVisitor.java +++ b/transformer/src/main/java/com/devexperts/aprof/transformer/AbstractMethodVisitor.java @@ -43,11 +43,13 @@ abstract class AbstractMethodVisitor extends MethodVisitor { protected final GeneratorAdapter mv; protected final Context context; + private final int classVersion; - public AbstractMethodVisitor(GeneratorAdapter mv, Context context) { + public AbstractMethodVisitor(GeneratorAdapter mv, Context context, int classVersion) { super(TransformerUtil.ASM_API, mv); this.mv = mv; this.context = context; + this.classVersion = classVersion; } protected abstract void visitMarkDeclareLocationStack(); @@ -193,7 +195,7 @@ public void visitMethodInsn(final int opcode, final String owner, final String n boolean isArrayClone = isClone && owner.startsWith("["); boolean isObjectClone = isClone && AProfRegistry.isDirectCloneClass(cname); - if (context.isMethodInvocationTracked(cname, opcode, owner, name, desc)) { + if (context.isMethodInvocationTracked(cname, opcode, owner, name, desc, classVersion)) { visitTrackedMethodInsn(opcode, owner, name, desc, intf); } else { mv.visitMethodInsn(opcode, owner, name, desc, intf); diff --git a/transformer/src/main/java/com/devexperts/aprof/transformer/Context.java b/transformer/src/main/java/com/devexperts/aprof/transformer/Context.java index aa4e2d0..127acdb 100644 --- a/transformer/src/main/java/com/devexperts/aprof/transformer/Context.java +++ b/transformer/src/main/java/com/devexperts/aprof/transformer/Context.java @@ -105,9 +105,13 @@ private void buildSignatureString(StringBuilder sb) { sb.append(')'); } - public boolean isMethodInvocationTracked(String cname, int opcode, String owner, String name, String desc) { + public boolean isMethodInvocationTracked(String cname, int opcode, String owner, String name, String desc, + int transformedClassVersion) + { if (owner.startsWith("[")) return false; // do not track array method invocations + if (transformedClassVersion >= Opcodes.V1_7 && TransformerUtil.INIT.equals(name)) + return false; // <init> invocations don't pass verifier in modern JVMs if (config.isMethodTracked(cname, name)) return true; // direct invocation of tracked method through its actual class if (opcode != Opcodes.INVOKEVIRTUAL && opcode != Opcodes.INVOKEINTERFACE) diff --git a/transformer/src/main/java/com/devexperts/aprof/transformer/MethodAnalyzer.java b/transformer/src/main/java/com/devexperts/aprof/transformer/MethodAnalyzer.java index d5c75de..a042bdf 100644 --- a/transformer/src/main/java/com/devexperts/aprof/transformer/MethodAnalyzer.java +++ b/transformer/src/main/java/com/devexperts/aprof/transformer/MethodAnalyzer.java @@ -28,8 +28,8 @@ * @author Dmitry Paraschenko */ class MethodAnalyzer extends AbstractMethodVisitor { - public MethodAnalyzer(GeneratorAdapter mv, Context context) { - super(mv, context); + public MethodAnalyzer(GeneratorAdapter mv, Context context, int classVersion) { + super(mv, context, classVersion); } @Override diff --git a/transformer/src/main/java/com/devexperts/aprof/transformer/MethodTransformer.java b/transformer/src/main/java/com/devexperts/aprof/transformer/MethodTransformer.java index c0a5b63..afcd8ae 100644 --- a/transformer/src/main/java/com/devexperts/aprof/transformer/MethodTransformer.java +++ b/transformer/src/main/java/com/devexperts/aprof/transformer/MethodTransformer.java @@ -37,8 +37,8 @@ class MethodTransformer extends AbstractMethodVisitor { private Label startFinally; - public MethodTransformer(GeneratorAdapter mv, Context context) { - super(mv, context); + public MethodTransformer(GeneratorAdapter mv, Context context, int classVersion) { + super(mv, context, classVersion); } private void pushAllocationPoint(String desc) {