Javaagent使用ASM进行字节码修改时跳过了部分类

最近在学习java的javaagent给函数插桩。
从github上随便找了个样例程序,发现UserDAO这个类在jsp预编译完成后(即第二次启动tomcat)怎么都插不上桩,只有删除jsp生成的class后才能正常插桩。
在transform里输出处理的所有类名,发现完全没有UserDAO这个类。
起初怀疑是ClassLoader的问题,但折腾了一天没有任何改变。
最后排查到了这里:

ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAME) {
    @Override
    protected ClassLoader getClassLoader() {
        return Thread.currentThread().getContextClassLoader();
    }
};
ClassVisitor cv = new ClassParser(cw);
byte[] bytes;
try {
    reader.accept(cv, ClassReader.SKIP_FRAME);
    bytes = cw.toByteArray();
} catch (Exception e) {
    e.printStackTrace();
    return code;
}

将COMPUTE_FRAME与SKIP_FRAME移除后,正常了

原因

根据这个回答描述的,COMPUTE_FRAME会尝试修改代码,让代码不用执行到原来的类中,也就造成了无缓存时,从原有文件读取代码,经过了javaagent的处理;而有缓存时,由于优化了路径,没有执行原来的类,也就没有读取并调用javaagent了,导致了缺少对应函数的插桩。

刚开始学习java,有什么不对欢迎指出owo

添加新评论