Я новичок в инструментарии агента Java и инструментарии ASM для байт-кода.Я взял код из этого учебного пособия по UCLA и использовал его для инструментария javagent, используя java.lang.instrument .
Первый вопрос: есть ли что-нибудь в библиотеке байт-кода ASM, чтонесовместимо с инструментарием javaagent?
Вот программа в несколько отредактированной форме:
public class Instrumenter {
public static void premain(String args, Instrumentation inst) throws Exception {
Transformer tr = new Transformer();
inst.addTransformer(tr);
}
}
class Transformer implements ClassFileTransformer {
public Transformer() {
}
@Override
public byte[] transform( ClassLoader loader, String className, Class<?> klass, ProtectionDomain domain, byte[] klassFileBuffer ) throws IllegalClassFormatException {
byte[] barray;
ClassWriter cwriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
ClassReader creader;
try {
creader = new ClassReader(new ByteArrayInputStream(klassFileBuffer));
} catch (Exception exc) {
throw new IllegalClassFormatException(exc.getMessage());
}
ClassVisitor cvisitor = new ClassAdapter(cwriter);
creader.accept(cvisitor, 0);
barray = cwriter.toByteArray();
return barray;
}
}
class ClassAdapter extends ClassVisitor implements Opcodes {
public ClassAdapter(ClassVisitor cv) {
super(ASM7, cv);
}
@Override
public MethodVisitor visitMethod( final int access, final String name, final String desc, final String signature, final String[] exceptions ) {
this.pwriter.println(ClassAdapter.nextMethodId + "," + this.className + "#" + name);
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
if (mv == null) {
return null;
} else {
return new MethodAdapter(mv);
}
}
}
class MethodAdapter extends MethodVisitor implements Opcodes {
public MethodAdapter(final MethodVisitor mv) {
super(ASM7, mv);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;");
mv.visitLdcInsn("CALL " + name);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
// do call
mv.visitMethodInsn(opcode, owner, name, desc, itf);
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;");
mv.visitLdcInsn("RETURN " + name);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
}
}
Таким образом, инструментарий javaagent работает на небольших программах.Я попытался запустить его на DaCapo suitemark , и он выдает ошибку StackOverflowError следующим образом:
Exception: java.lang.StackOverflowError thrown from the UncaughtExceptionHandler in thread "main"
Когда я удаляю инструкции, добавленные в visitMethodInsn, агент успешно работает.Я исследовал этот бит еще немного и нашел в документах ASM о необходимости вызова MethodVisitor.visitMaxs .Похоже, что это наиболее вероятная причина ошибки StackOverflowError.
Итак, дополнительные вопросы:
- Это так?Должен ли я позвонить в VisitMaxs в какой-то момент?Если да, то где?
- Если нет, то что я делаю не так?Или что я должен делать, чтобы избежать переполнения стека?