Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,11 @@
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.pool.TypePool;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.JSRInlinerAdapter;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.Analyzer;
Expand Down Expand Up @@ -487,9 +490,10 @@ private byte[] writeClassFile(
classNode.version = Opcodes.V1_8;
}
ClassWriter writer = new SafeClassWriter(loader);
ClassVisitor visitor = new JsrInliningClassVisitor(writer);
LOGGER.debug("Generating bytecode for class: {}", Strings.getClassName(classFilePath));
try {
classNode.accept(writer);
classNode.accept(visitor);
} catch (Throwable t) {
LOGGER.error("Cannot write classfile for class: {} Exception: ", classFilePath, t);
reportInstrumentationFails(definitions, Strings.getClassName(classFilePath));
Expand Down Expand Up @@ -929,6 +933,26 @@ private static Path dumpClassFile(String className, byte[] classfileBuffer) {
}
}

/**
* A {@link org.objectweb.asm.ClassVisitor} that uses {@link
* org.objectweb.asm.commons.JSRInlinerAdapter} to remove JSR instructions and inlines the
* referenced subroutines. This allows pre-Java 6 classes with finally blocks to be successfully
* transformed. Without this an IllegalArgumentException for "JSR/RET are not supported with
* computeFrames option" would be thrown when writing the transformed class.
*/
static class JsrInliningClassVisitor extends ClassVisitor {
protected JsrInliningClassVisitor(ClassVisitor parent) {
super(Opcodes.ASM9, parent);
}

@Override
public MethodVisitor visitMethod(
int access, String name, String descriptor, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
return new JSRInlinerAdapter(mv, access, name, descriptor, signature, exceptions);
}
}

static class SafeClassWriter extends ClassWriter {
private final ClassLoader classLoader;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,24 @@ public void veryOldClassFile() throws Exception {
assertOneSnapshot(listener);
}

/**
* Ensure older pre-Java 6 class files with JSR/RET can be rewritten without "JSR/RET are not
* supported with computeFrames option" exceptions being thrown.
*/
@Test
public void veryOldClassFileWithJsrRet() throws Exception {
final String CLASS_NAME = "antlr.Tool"; // compiled with jdk 1.2
TestSnapshotListener listener = installMethodProbe(CLASS_NAME, "copyFile", null);
Class<?> testClass = Class.forName(CLASS_NAME);
assertNotNull(testClass);
try {
Reflect.onClass(testClass).create().call("copyFile", null, null);
} catch (Throwable t) {
// ignore
}
assertOneSnapshot(listener);
}

@Test
public void oldClass1_1() throws Exception {
final String CLASS_NAME = "org.apache.commons.lang.BooleanUtils"; // compiled with jdk 1.1
Expand Down
Loading