• 14
  • 15
分享

一、前言

在字节码编程方面有三个比较常见的框架;ASM、byte-buddy、Javassist,他们都可以对这字节码进行操作,只是操作方式和控制粒度不同。

其中 ASM 更偏向于底层,需要了解 JVM 虚拟机中指定规范以及对局部变量以及操作数栈的知识。虽然在编写起来比较麻烦,但是它也是性能最好功能最强的字节码操作框架。常见的会用在 CGLIB 动态代理类中,以及一些非入侵的探针监控场景中。

另外两个框架都是有强大的 API,操作使用上更加容易控制。虽然对对比上会比 ASM 性能差一些,但不是说性能完全不好。同样在一些监控场景中也用的非常多。如果你细心可以在你的工程 jar 包搜索一下。

在这之前我已经编写了 Javaagent全链路监控 和 ASM 的部分文章,虽然这部分技术内容在 CRUD 开发中并不常用,但随着自动化测试、非入侵监控的大量使用,还是蛮多人需要这样的技能学习的。同时我也是这样一个技能的学习者,为此后面会陆续编写和完善关于 字节码编程 这个专栏。也希望这个专栏在提升自己技术栈的同时也帮助他人成长。

二、开发环境

1、JDK 1.8.0

2、javassist 3.12.1.GA

<dependency>
    <groupId>javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.12.1.GA</version>
    <type>jar</type>
</dependency>

三、案例目标

不看实现过程的话,我们的案例目标其实很简单,就是使用 javassist 输出一行 Helloworld 。这话像不像产品说的

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("javassist hi helloworld by 小傅哥(bugstack.cn)");
    }
    public HelloWorld() {
    }
}

以上的这段代码就是我们接下来需要使用字节码编程技术来实现的内容。

四、技术实现

其实输出一个 Helloworld 还是蛮简单的,主要是从这里面去学习一下 Javassist 的基本语法结构,也能为后续的学习有一个基础的概念。

javassist Helloworld
/**
 * 公众号:bugstack虫洞栈
 * 博客栈:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
 * 本专栏是小傅哥多年从事一线互联网Java开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程。如果能为您提供帮助,请给予支持(关注、点赞、分享)!
 */
public class GenerateClazzMethod {
    public static void main(String[] args) throws IOException, CannotCompileException, NotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        ClassPool pool = ClassPool.getDefault();
        // 创建类 classname:创建类路径和名称
        CtClass ctClass = pool.makeClass("org.itstack.demo.javassist.HelloWorld");
        // 添加方法
        CtMethod mainMethod = new CtMethod(CtClass.voidType, "main", new CtClass[]{pool.get(String[].class.getName())}, ctClass);
        mainMethod.setModifiers(Modifier.PUBLIC + Modifier.STATIC);
        mainMethod.setBody("{System.out.println(\"javassist hi helloworld by 小傅哥(bugstack.cn)\");}");
        ctClass.addMethod(mainMethod);
        // 创建无参数构造方法
        CtConstructor ctConstructor = new CtConstructor(new CtClass[]{}, ctClass);
        ctConstructor.setBody("{}");
        ctClass.addConstructor(ctConstructor);
        // 输出类内容
        ctClass.writeFile();
        // 测试调用
        Class clazz = ctClass.toClass();
        Object obj = clazz.newInstance();
        Method main = clazz.getDeclaredMethod("main", String[].class);
        main.invoke(obj, (Object)new String[1]);
    }
}

这段代码分为几块内容来实现功能,分别包括;

  1. 创建 ClassPool,它是一个基于HashMap实现的 CtClass 对象容器。

  2. 使用 CtClass,创建我们的类信息,也就是类的路径和名称。

  3. 接下来就是给类添加方法。包括;方法的属性、类型、名称、入参、出参和方法体的内容。

  4. 在方法创建好后还需要创建一个空的构造函数,每一个类都会在编译后生成这样一个构造函数。

  5. 当方法创建完成后,我们使用 ctClass.writeFile() 进行输出方法的内容信息。也就可以看到通过我们使用 Javassist 生成类的样子。

  6. 最后就是我们的反射调用 main 方法,测试输出结果。

五、测试结果

当我们执行测试的时候会输出类信息到工程文件夹下,同时会输出我们的测试结果;

1. 使用Javassist生成的类

使用Javassist生成的类,在工程文件夹下

1.png

2. 输出的测试结果

javassist hi helloworld by 小傅哥(bugstack.cn)
Process finished with exit code 0

六、总结

  • 关于 Javassist 的使用在完整的且强大的 API 下,确实还是蛮容易使用的。并且代码的使用上并不是很难理解。

  • 后续会陆续推出字节码编程的案例文章,逐步完善这部分技术知识栈的内容。最终尝试使用这样的技术知识完成一个案例级别的质量检测系统。也欢迎喜欢此类内容的小伙伴跟进学习。

  • 后续的文章可能在专栏类的文章里,文章内容上会短一点。尽可能在一篇文章中描述清楚一个详尽的知识点,也方便后续整理成 PDF 书籍,方便学习使用。


作者:小傅哥

原文链接:https://www.cnblogs.com/xiaofuge/p/12846347.html

  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          • 重新认识自动化测试我从事软件测试工作以来,第一次知道自动化是 15 年年底,听大佬说 QTP 可以录制脚本然后自动化回放,测试效率很高,当时心向往之。不过当时技术比较菜,而且对工作也比较迷茫,听过就忘记了。大概 16 年时候,测试圈子自动化测试开始火爆了起来,当时基于 selenium 的 UI 自动化测试特别火爆。圈子里讨论,培训班推广,很多关于基于 selenium 的 UI 自动化测试的技术文章和书籍开始不断涌现。我本人是 17 年年初才开始学习自动化测试并且尝试在工作中应用的,确实在回归测试和造数据方面,给了我很多的帮助,当然由于比较早吃螃蟹,在后面跳槽找工作时候,涨薪幅度也挺大。大概...
            0 0 2087
            分享
          •   手机App软件与Web软件系统的架构是不一样的,手机是基于CS架构,而Web系统是基于BS架构的,所以测试手机App软件那么要考虑的东西会更多一些。  手机App测试,虽然要比Web测试复杂一些,但系统整理起来后,主要也就下面几个方面:  一、App功能测试(也叫App手工测试)  APP功能测试是指测试你这个APP的所有功能点是否能够验证通过。APP功能测试的测试用例设计需要结合产品需求和开发设计文档。这里以测试微博APP为例:  1. 发布微博,从界面上看有文字长度,是否添加图片,是否有话题,是否有@别人等等。  2. 发布微博的操作是否符合用户体验,选择照片,选择要@的人是否符合人类...
            12 12 2692
            分享
          •   有道是:“观史知今当思进退,读书养志可识春秋”。  列数最近十年的重要进展,其目的还是要我们带着发展的眼光,来预测未来几年测试领域的发展,提前做好准备。  所以为了让大家阅读此文后有尽可能强烈的获得感,本文行文结构如下:  一、回顾软件测试发展的五个重要时期:  ·1957之前 - 以调试为主:独自承担需求分析,设计,研发,调试,也就是Debug。  · 1957-1978 - 以证明为主:确保程序解决它该解决的问题,证明软件是否符合需求,证明确实是有缺陷的。  · 1979-1982 - 以破坏为主:在符合需求的情况下,通过异常测试的方法,明确软件应该做什么,不应该做什么。  · 198...
            0 0 1372
            分享
          • Postman Newman 是什么?Postman Newman 是一个 CLI(命令行界面)工具,可以使用它来运行 Postman 中的集合(Collection)和环境(Environment)进行自动化测试。它是 Postman 的命令行 Collection Runner,能够直接从命令行运行 Postman 集合。使用 Newman 可以测试 API 的功能、性能、可靠性和安全性,同时可以将测试结果输出成多种格式的报告,例如 HTML、JSON、JUnit 等,以方便开发人员进行问题定位和分析。Postman Newman 的作用通过 Postman Newman 进行自动化...
            0 0 1088
            分享
          •   功能测试  1、不说话的时候发送语音, 是否会有相关的信息提示。  2、说话分贝很轻很轻, 是否可以录入语言。  3、普通的语音信息是否可以正常发送。  4、语音录制的时候是否有时间限制(最短限制 / 最长限制)。  5、录制时间不足最短时长限制会发送失败。  6、超出了最长时间限制时, 语音自动保存并发送。  7、语音识别。     · 是否可以录入中文, 英文, 日语…     · 是否可以录入小动物的声音: 狗叫, 猫叫, 羊叫…     · 是否可以录入其他声音: 汽笛, 施工声…  8、是否可以取消语...
            0 0 5770
            分享
      • 51testing软件测试圈微信