2 如何用ASM进行插桩

2023-10-27

假如我们现在有这样一个文件,代码如下:

public class Hello {
    public String name = "hello";

    public static void main(String[] args){
        System.out.println("Hello, world");
    }
}

我们想要知道它的哪些指令被执行了,因此我们需要对其编译过后的class文件中的指令进行插桩。下面讲解具体做法。

首先,我们需要读取要被插桩的文件:

InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("Hello.class");
        
ClassWriter cw = new ClassWriter(0);
ClassReader reader = new ClassReader(is);
reader.accept(new ClassAdapter(ASM9, cw), 0);

byte[] code = cw.toByteArray();

同时,我们为了能够插桩还需要重写ClassVisitor和MethodVisitor的方法。

为了能够对class文件插桩,我们需要访问class文件的method部分,因此我们需要重写methodVisitor的方法。为此我们使用一个名为ClassAdapter的类继承ClassVisitor,代码如下:

class ClassAdapter extends ClassVisitor implements Opcodes {
    public ClassAdapter(int api, ClassVisitor cv) {
        super(api, cv);
    }
    
    public MethodVisitor visitMethod(int access, String name,
                                     String desc, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
        return new MethodAdaptor(this.api, mv);
    }
}

因为我们是要在每一条指令执行之前插桩,所以我们还需要重写visitXXXInsn,所以我们还需要新建一个继承于MethodVisitor的类。假如我们需要对所有zero operand类型的指令进行插桩,那么MethodVisitor的写法如下:

class MethodAdaptor extends MethodVisitor implements Opcodes {
    public MethodAdaptor(int api, MethodVisitor mv) {
        super(api, mv);
    }
    
    @Override
    public void visitInsn(int opcode) {
        mv.visitIntInsn(SIPUSH, opcode);
        mv.visitMethodInsn(INVOKESTATIC, "insert", "beforeInvoke", "(I)V", false);
        super.visitInsn(opcode);
    }
}

其它类型指令的插桩方法大同小异。

其中:

mv.visitIntInsn(SIPUSH, opcode);
mv.visitMethodInsn(INVOKESTATIC, "insert", "beforeInvoke", "(I)V", false);

这段代码的作用是掉用另一个类的静态方法来打印即将被执行的指令对应的opcode,另一个类的写法如下:

public class insert {
    public static void beforeInvoke(int opcode) {
        System.out.println("before "+opcode);
    };
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

2 如何用ASM进行插桩 的相关文章

随机推荐

  • PCL学习(1)PCL初玩

    PCL学习 文章目录 PCL学习 toc 前言 安装 说明 一步步引导做例子 关于CMakeLists txt 具体实践 官网的例子 解释 参数 总结 前言 最近进行毕设论文的设计时 博主学习计算机相关学习的过程中 但是浏览中感觉PCL进行
  • 阿里云Linux服务器安装配置MongoDB,并用navicat连接

    一 下载并安装MongoDB 1 首先下载 MongoDB 并上传至服务器 2 下载完成后解压文件 tar zxvf mongodb linux x86 64 4 0 11 tgz 3 移动到安装目录 mv mongodb linux x8
  • IntelliJ IDEA使用_Debug操作

    文章目录 版本说明 图标和快捷键 查看变量 计算表达式 条件断点 多线程调试 版本说明 当前的IntelliJ IDEA 的版本是2021 2 2 下载IntelliJ IDEA ps 不同版本一些图标和设置位置可能会存在差异 但应该大部分
  • 【AcWing】827. 双链表

    双链表 实现一个双链表 双链表初始为空 支持5种操作 在最左侧插入一个数 在最右侧插入一个数 将第 k个插入的数删除 在 第 k个插入的数左侧插入一个数 在第 k个插入的数右侧插入一个数 现在要对该链表进行 M次操作 进行完所有操作后 从左
  • 计蒜客 17319 The Heaviest Non-decreasing Subsequence Problem

    Problem nanti jisuanke com t 17319 Meaning 给一个整数序列 s 每个数都有个权值 权值的计算方法是 s i lt 0 s i 的权值为 0 s i gt 10000 s i 的权值为 5 且 s i
  • tomcat配置SSL证书_tomcat配置https证书

    现在很多网站都采用了https 因为https比http安全 所以我们公司也把内网系统改成https访问 但是这个要怎么配置和申请证书呢 如果企业不缺钱的情况下申请购买SSL证书 当然也可以申请免费的ssl证书 我们公司就是申请免费的SSL
  • 使用ByteArrayOutputStream将数据写入本地文件

    使用ByteArrayOutputStream将数据写入本地文件 在一个项目中做一次性校验部分 需要将校验后数据写入表格后上传 巧的是 服务器Down了 作为一个新手实习生菜鸟 为了测试自己的代码和输出结果有没有毛病 在大神同事的指点下选择
  • 单片机RAM使用与优化

    一 单片机中会使用 RAM 的内容有 变量 数组 堆栈 中断向量表等 其中变量和数组是程序中定义的变量和数组 用于存储程序运行时需要的数据 堆栈用于保存函数调用和返回的地址和参数等信息 中断向量表用于存储中断服务程序的入口地址 RAM 的读
  • 几个cve漏洞库查询网站

    分享几个cve漏洞库查询网站 自己在工作中经常用到 阿里云漏洞库 https avd aliyun com nvd list tenable漏洞库 nessus https www tenable com cve search https
  • 使用Google Weather API查询天气预报

    Google Weather API 只支持美国地区使用邮政编码进行查询 例如 http www google com ig api hl zh cn weather 94043 94043 为 山景城 美国加州 的邮政编码 而除了美国以外
  • IntelliJ换行CRLF, LF, CR的解释和默认设置

    在window下开发有一个大坑 就是换行默认是CRLF 也就是回车换行 但是Linux下只有换行LF 这样代码提交后 会出现编译问题 所以最好的办法是在IntelliJ下设置默认为LF 首先我们先介绍CRLF LF和CR这三种东西 CR是M
  • Android RecyclerView 网格显示正方形元素

    使用recyclerView显示纵向滑动的网格列表 只需要设置 mListView setLayoutManager new GridLayoutManager context 4 其中第二个参数4代表一行显示4个元素 但是如果要让元素为正
  • 以太坊(一)——概述

    一 以太坊出现的原因 比特币的不足 交易速度慢 出块时间为10分钟 采用POW算法 拼的是计算机的算力 耗电量大 会释放大量的温室气体 仅仅完成了货币的去中心化 以太坊的解决方法 交易速度加快 出块时间为15秒 以太币为10分钟 采用POW
  • 跟着 Guava 学 Java 之缓存

    本文我们先介绍一些缓存的背景知识 以及内存缓存的流行开源库类实现 最后利用一些例子重点介绍下 Guava Cache 的缓存功能 背景 什么是缓存 在计算中 缓存是一个高速数据存储层 其中存储了数据子集 且通常是短暂性存储 这样日后再次请求
  • 数据结构——排序

    目录 一 排序算法的基本概念 1 1 排序算法的分类 1 1 1 内部排序 1 1 2 外部排序 二 插入排序 三 希尔排序 四 冒泡排序 五 快速排序 六 简单选择排序 七 堆排序 7 1 建立大根堆 7 2 基于大根堆进行排序 7 3
  • VS Code IDE 安装使用教程

    概念 VS Code Visual Studio Code 是一个轻量级但功能强大的源代码编辑器 可用于Windows macOS 和Linux 它内置了对 JavaScript TypeScript和Node js的支持 并具有丰富的扩展
  • opencv-python 实现鱼眼矫正 棋盘矫正法

    鱼眼矫正有很多的方法 比较常用的有 棋盘标定法 经纬度法 opencv自带鱼眼矫正算法 也就是第一种 棋盘矫正法 第一步 制作棋盘格 用A4纸打印一张棋盘格 固定到硬纸板上 然后用鱼眼镜头对着拍摄 保留拍到的图片 如下图所示 可以从不同角度
  • SpringBoot学习:整合shiro(rememberMe记住我后自动登录session失效解决办法)

    项目下载地址 http download csdn NET detail aqsunkai 9805821 定义一个拦截器 判断用户是通过记住我登录时 查询数据库后台自动登录 同时把用户放入session中 配置拦截器也很简单 Spring
  • 焦距、物距与像距

    基础知识 公式 1 焦距 1 物距 1 像距 焦距的最大值和最小值的比就是几倍变焦焦距的最大值和最小值的比就是几倍变焦 对焦 聚焦 指的是改变的是像距 一般是移动成像面 如上图靶面 变焦 调焦 指的是改变的是镜头焦距 一般是移动镜头
  • 2 如何用ASM进行插桩

    假如我们现在有这样一个文件 代码如下 public class Hello public String name hello public static void main String args System out println He