基于上一篇的方法插桩,这一篇则是进一步的对每行的语句进行插桩。

对于存在分支的方法(例如if(){}else{}),对方法插桩的方法是不能够全部涉及到的。所以要对程序的每条语句进行插桩。

插入什么语句呢?可以插入包括以下的内容:

1‘  classname

2’  linenumber

此时需要用到javassist  api里的类CtMethod的方法insertAt(),对程序的每条语句进行插桩。

逻辑思想就是:读取class文件,对类的方法进行获取,读取每个类的行号范围,在每个行号前用insertAt()方法插入语句,输出行号和类名。

示例代码如下:

import java.io.IOException;
import javassist.*; public class TriangleInsertAt {
public static void main(String args[]) throws NotFoundException, CannotCompileException, IOException{
//获取class文件
CtClass clas=ClassPool.getDefault().get("Triangle");
if(clas==null){
//方法未找到
System.out.println("classname "+clas+" not found");
}else{
//isTriangle方法的行号范围
//此处对Triangle四个方法分别进行语句插桩
insertToLine(clas,"isTriangle",31,48);
insertToLine(clas,"getType",55,77);
insertToLine(clas,"diffOfBorders",83,85);
insertToLine(clas,"getBorders",90,96);
clas.writeFile();
}
}
public static void insertToLine (CtClass ccl,String method,int i,int j) throws NotFoundException, CannotCompileException{
//获取方法信息,如果方法不存在,则抛出异常
CtMethod ctMethod = ccl.getDeclaredMethod(method);
//将旧的方法名称进行重新命名
String nname = method + "$impl";
ctMethod.setName(nname);
//方法的副本
CtMethod newCtMethod = CtNewMethod.copy(ctMethod, method, ccl, null);
//用for循环语句插桩
for(;i<j;i++){
newCtMethod.insertAt(i,true,"System.out.println(\" classname "+ccl.getName()+" linenumber \"+" + i +");");
}
ccl.addMethod(newCtMethod);
System.out.println("run to here");
}
}

▲ 代码中插入输出语句的那行 

newCtMethod.insertAt(i,true,"System.out.println(\" classname "+ccl.getName()+" linenumber  \"+" + i +");");
  这里需要注意引号的不同意义,\" \"是双引号的转义字符,而加号也是有此处字符串相加的,也有System.out.println()里的输出之间的加号。
 

这只是一个基于方法插桩的语句插桩,逻辑缜密上并不完善,待要解决的存有:

1‘  获取行号,需要借助于文件复制,在每循环一次readLine方法,就对linenumber执行+1,在此需要做出判断,该行是否为方法体,构造函数,main方法,注释,空行(此处的空行为代码里的空行,并不意味着null而是换行的“\n”),创建一个数组,对特殊行号进行标记,我目前的思想是构造二维数组,记录行号和该行的属性。(此处需用到IO流的文件读取和写入的方法,在判断时会用到contains()和startwith()方法等;

2’  根据上述的代码生成一个新的class文件,借助工具查看插桩后的java代码,会发现输出的行号并不是按顺序,而且有的行没有,有的行有两次输出。此为编译后生成的class文件的显示。

对此,需要进行缜密的插入判断,借助于第一条的建议进行判断性的插入。

3‘  整个程序中需要语句插桩的有main方法,构造函数,方法,此代码对前两者并没有插入,问题出在还借用了方法插桩的方法,对方法进行重命名,插入输出语句,然后将新的方法也写入到源文件中。而语句插桩并不需要重写方法,而是直接经过判断将输出语句写入到每行符合条件的代码前。输出的结果应该并没有整个程序的行数那么多,而且行数需递增型输出。

总结:

java基础重中之重,仅是一个简单的语句插桩就涉及到了文件复制,读取判断,提取字符串,迭代,Javassist API和JDK API都需要运用到很多方法。

将语句插桩进一步完善的思路:首先文件复制时,创建数组记录行数和出现方法和构造函数的特殊行数;其次读取class文件时,用到CtMethod类的insertAt方法进行选择性的插桩,注释,构造方法的那一行,以及类似“\n”," }","{"之类的字符串都要进行排除;之后运行需要进一步完善不足之处。

一个功能只能经过不断地完善才能尽量的减少bug和提升性能,没有十全十美之时。

Javsssist用InsertAt()方法对语句插桩的更多相关文章

  1. Javassist进行方法插桩

    javassist官网 http://jboss-javassist.github.io/javassist/ javassist API网 http://jboss-javassist.github ...

  2. zorka源码解读之通过beanshell进行插桩的流程

    zorka中插桩流程概述 1.在SpyDefinition中配置插桩属性,将SpyDefinition实例提交给插桩引擎.2.SpyDefinition实例中包含了插桩探针probes,probe插入 ...

  3. APK修改神器:插桩工具 DexInjector

    本文介绍了一个针对Dex进行插桩的工具,讲解了一下直接修改Dalvik字节码和Dex文件时遇到的问题和解决方法 作者:字节跳动终端技术-- 李言 背景 线下场景中,我们经常需要在APK中插入一些检测代 ...

  4. 插桩 inline hook 动态二进制插桩的原理和基本实现过程

    插桩测试 https://source.android.google.cn/compatibility/tests/development/instrumentation https://zhuanl ...

  5. 开发 IDEA Plugin 引入探针,基于字节码插桩获取执行SQL

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 片面了! 一月三舟,托尔斯泰说:"多么伟大的作家,也不过就是在书写自己的片 ...

  6. Java Instrumentation插桩技术学习

    Instrumentation基础 openrasp中用到了Instrumentation技术,它的最大作用,就是类的动态改变和操作. 使用Instrumentation实际上也可以可以开发一个代理来 ...

  7. 手淘架构组最新实践 | iOS基于静态库插桩的⼆进制重排启动优化 抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15% 编译期插桩

    抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15% 原创 Leo 字节跳动技术团队 2019-08-09 https://mp.weixin.qq.com/s/Drmmx5JtjG ...

  8. 方案设计:基于IDEA插件开发和字节码插桩技术,实现研发交付质量自动分析

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 如何保证代码质量? 业务提需求,产品定方案,研发做实现,测试验流程.四种角色的相互配 ...

  9. Flymeos插桩适配教程

    插桩适配前提,安装Ubuntu或者其他linux系统. 安装JDK7 sudo apt--jdk Ubuntu 16.04与基于它的版本,需要添加源 sudo add-apt-repository p ...

随机推荐

  1. 解决R语言临时文件目录的问题(tempdir、tempfile)

    最近在调用SparkR的时候,当用copy_to函数将R中的数据框导入到Spark时,会在默认的tempdir()目录下(这里默认目录即为/tmp)产生巨大的临时文件, 严重影响R脚本的运行,最终一番 ...

  2. Eclipse之文件【默认编码格式设置】,防止乱码等问题

    文件默认编码格式设置步骤如下: 这里显示的是workspace的视图 其他格式文件的视图如下:

  3. 一天搞定CSS:定位position--17

    1.定位取值概览 2.相对定位relative <!DOCTYPE html> <html> <head> <meta charset="UTF-8 ...

  4. Publishing failed with multiple errors.问题解决

    问题:Publishing failed with multiple errors.(发布失败与多个错误) 原因:项目工程文件删除,但eclipse里面仍显示存在. 解决方案:刷新项目工程,重新部署, ...

  5. 搭建rtmp直播流服务之2:使用java实现ffmpeg命令接口化调用(用java执行ffmpeg命令)

    欢迎大家积极开心的加入讨论群 群号:371249677 (点击这里进群) 一.环境搭建 1.安装ffmpeg 下载对应系统的ffmpeg安装包,个人采用windows平台进行开发,所以安装了windo ...

  6. CentOS6.8安装python2.7以及XX-Net

    xx-net在ubuntu上运行用起来很方便,如果有一些原因必须用CentOS,麻烦就比较大了. 首先需要升级python版本,CentOS自带的2.6版本是用不了的,必须升级到2.7以上,但是不能用 ...

  7. JQuery树形目录插件Dynatree

    最近做网页需要做一个树形目录功能.找了一下发现有很多JQuery插件都可以实现这个功能.选了一个自己觉得最满意的插件Dynatree做个学习笔记. 可以把静态的html转成树形目录,还可以动态创建添加 ...

  8. python 解析docx文档的方法,以及利用Python从docx文档提取插入的文本对象和图片

    首先安装docx模块,通过pip install docx或者在docx官方链接上下载安装都可以 下面来看下如何解析docx文档:文档格式如下 有3个部分组成 1 正文:text文档 2 一个表格. ...

  9. CSS技巧和经验列表

    如何清除图片下方出现几像素的空白间隙? img{display:block;} 如何让文本垂直对齐文本输入框? input{vertical-align:middle;} 如何使文本溢出边界显示为省略 ...

  10. 可能是最详细的 Hexo + GitHub Pages 搭建博客的教程

    前言:博主目前大三,Web 前端爱好者.写博客的好处,不是为了写而写,而是一个记录思想的过程.不要考虑它能带给你什么,而是你自己从中收获了什么. 最近刚好有空,于是就参照网上的各种教程,搭建了一个博客 ...