Errors caused by already instrumented classes
Lukas Marek <[email protected]>
| Newsgroups | gmane.comp.java.objectweb.asm |
|---|---|
| Message-ID | <[email protected]> |
Hello, we are instrumenting classes using two our own tools build on top of the ASM. Both tools are used in a chain where classes are passed as bytes between the tools. Both tools should produce valid class as their output. We encountered some errors in ASM when passing instrumented class from the first tool to the second one. In the first tool, the class is properly (with no errors) instrumented and validated using CheckClassAdapter. They are also successfully loaded with jvm if the second instrumentation tool is skipped. There are two cases where the ASM fails to load the classes produced by the first tool. I've created byte dumps of the class produced by the first tool and simple asm test cases where it fails in the second one. In the first scenario called "example1", if the "CheckClassAdapter" is removed, everything works fine. Otherwise, it produces ArrayIndexOutOfBoundsException in MethodWriter class. Second scenario (example2) uses ClassVisitor and AdviceAdapter. If the AdviceAdapter is replaced with MethodVisitor, everything works fine. EditA and A sources should be another example of the second scenario done by my colleague. We are using ASM 4.0 RC2. Lukas Marek
Example1.java
(text/plain, 773 B)
import java.io.FileInputStream;
import java.io.IOException;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.util.CheckClassAdapter;
public class Example1 {
public static void main(String[] args) throws IOException {
FileInputStream is = new FileInputStream("example1.class");
ClassReader cr2 = new ClassReader(is);
ClassNode cn2 = new ClassNode(Opcodes.ASM4);
cr2.accept(cn2, ClassReader.SKIP_DEBUG | ClassReader.EXPAND_FRAMES);
cn2.accept(new CheckClassAdapter(new ClassWriter(
ClassWriter.COMPUTE_MAXS)));
ClassWriter cw2 = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cn2.accept(cw2);
cw2.toByteArray();
}
}
Example2.java
(text/plain, 1.1 KB)
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
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.AdviceAdapter;
import org.objectweb.asm.util.CheckClassAdapter;
import org.objectweb.asm.util.TraceClassVisitor;
public class Example2 {
public static void main(String[] args) throws IOException {
FileInputStream is = new FileInputStream("example2.class");
ClassReader cr = new ClassReader(is);
ClassWriter cw = new ClassWriter(cr, 0);
cr.accept(new CheckClassAdapter(
new TraceClassVisitor(new PrintWriter(System.out))), 0);
cr.accept(new ClassVisitor(Opcodes.ASM4, cw) {
@Override
public MethodVisitor visitMethod(int access, String name,
String desc, String sig, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, sig,
exceptions);
return new AdviceAdapter(Opcodes.ASM4, mv, access, name, desc) {};
// return new MethodVisitor(Opcodes.ASM4, mv) {};
}
}, 0);
}
}
example1.class
(application/octet-stream, 15 KB) - not displayed
example2.class
(application/octet-stream, 16.6 KB) - not displayed
A.java
(text/plain, 151 B)
public class A {
public int a;
public A() {
a = 0;
}
public static void main(String[] args) {
A a = new A();
System.out.println(a.a);
}
}
EditA.java
(text/plain, 2.2 KB)
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.AdviceAdapter;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.util.CheckClassAdapter;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceMethodVisitor;
public class EditA {
public static void main(String[] args) throws AnalyzerException {
try {
ClassReader cr = new ClassReader(
EditA.class.getResourceAsStream("A.class"));
ClassNode cn = new ClassNode();
cr.accept(cn, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
MethodNode method = cn.methods.get(0);
InsnList ilst = method.instructions;
AbstractInsnNode first = ilst.getFirst();
LabelNode start = new LabelNode();
LabelNode end = new LabelNode();
LabelNode after = new LabelNode();
ilst.insertBefore(first, start);
ilst.insertBefore(first, new JumpInsnNode(Opcodes.GOTO, after));
ilst.insertBefore(first, end);
ilst.insertBefore(first, new InsnNode(Opcodes.ATHROW));
ilst.insertBefore(first, after);
method.tryCatchBlocks.add(new TryCatchBlockNode(start, end, end,
null));
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
CheckClassAdapter cca = new CheckClassAdapter(cw);
cn.accept(cca);
File f = new File("A.class");
FileOutputStream fos = new FileOutputStream(f);
fos.write(cw.toByteArray());
fos.flush();
fos.close();
// fails
AdviceAdapter aa = new AdviceAdapter(Opcodes.ASM4,
new TraceMethodVisitor(new Textifier()),
Opcodes.ACC_PUBLIC, method.name, method.desc) {
@Override
protected void onMethodEnter() {
super.onMethodEnter();
}
};
method.accept(aa);
} catch (IOException e) {
e.printStackTrace();
}
}
}
message-footer.txt
(text/plain, 238 B)
-- You receive this message as a subscriber of the [email protected] mailing list. To unsubscribe: mailto:[email protected] For general help: mailto:[email protected]?subject=help OW2 mailing lists service home page: http://www.ow2.org/wws