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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.