修改 Javassist 中的行号

2023-11-29

所以我最近一直在使用Javassist,但我遇到了一个我无法找到答案的问题。 CtMethod 的 insertAt 方法允许您在特定行号处插入代码,但它会覆盖该行还是保留它,以及如何使其执行与默认情况相反的操作?我有一个应用程序,它在运行之前使用 Javassist 根据 XML 文件中的“钩子”修改源代码。我想这样做,以便可以覆盖一行,或者可以将一行放在该行上方而不是覆盖它。显然有一些黑客方法可以做到这一点,但我宁愿使用正确的方法。


简单的部分

方法insertAt(int 行号, 字符串 src)CtMethod 对象中存在的内容允许注入编写的代码src before给定行中的代码。

例如,采用以下(简单)示例程序:

public class TestSubject {

   public static void main(String[] args) {
     TestSubject testSubject = new TestSubject();
     testSubject.print();
   }

   private void print() {
    System.out.println("One"); // line 9
    System.out.println("Two"); // line 10
    System.out.println("Three"); // line 11
   }
}

通过简单的编码(记住方法变量必须是 CtMethod 表示print方法):

   // notice that I said line 10, which is where the sysout of "two" is
   method.insertAt(10, true, "System.out.println(\"one and an half\");");

将在类中注入新的 sysout 指令。新类的输出将是:

 one
 one and an half
 two 
 three

困难的部分

Javassist 没有提供删除一行代码的简单方法,因此如果您确实想替换它,您将别无选择,只能破解。

怎么做?好吧,让我向您介绍一下您的新朋友(如果您还不认识),代码属性 object.

CodeAttribute 对象负责保存表示方法流程的字节码,除了 code 属性之外,还有另一个属性称为行号属性这可以帮助您将行号映射到字节码数组中。所以总结一下这个对象已经有你需要的一切了!

以下示例中的想法非常简单。将字节码数组中的字节与应删除的行相关联,并用无操作代码替换这些字节。

再次强调,method 是 method 的 CtMethod 表示print

    // let's erase the sysout "Two"
    int lineNumberToReplace = 10;
    // Access the code attribute
    CodeAttribute codeAttribute = method.getMethodInfo().getCodeAttribute();

    // Access the LineNumberAttribute
    LineNumberAttribute lineNumberAttribute = (LineNumberAttribute)      codeAttribute.getAttribute(LineNumberAttribute.tag);

    // Index in bytecode array where the instruction starts
    int startPc = lineNumberAttribute.toStartPc(lineNumberToReplace);

    // Index in the bytecode array where the following instruction starts
    int endPc = lineNumberAttribute.toStartPc(lineNumberToReplace+1);

    System.out.println("Modifying from " + startPc + " to " + endPc);

    // Let's now get the bytecode array
    byte[] code = codeAttribute.getCode();
    for (int i = startPc; i < endPc; i++) {
      // change byte to a no operation code
       code[i] = CodeAttribute.NOP;
    }

在中运行此修改originalTestSubject 类将生成具有以下输出的注入类:

 one
 three

加起来

当您需要添加一行并仍保留现有行时,您只需使用中给出的示例简单的部分如果要替换该行,则必须首先使用中给出的示例删除现有行困难的部分然后使用第一个示例注入新行。

另请记住,在示例中,我假设您已经熟悉了 javassist 的基础知识,仅向您展示了有趣的部分,而不是全部内容。这就是为什么,例如,在示例中没有 ctClass.writeFile...您仍然需要这样做,我只是将其省略,因为我确实希望您应该知道您必须这样做。

如果您在代码示例中需要任何额外帮助,请直接询问。我很乐意提供帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

修改 Javassist 中的行号 的相关文章

  • Java Runtime.getRuntime().freeMemory() 问题

    我搜索并看到了一些线程 但没有一个能够解决我遇到的具体问题 我正在尝试使用以下方式监视我的内存使用情况Runtime getRuntime freeMemory Runtime getRuntime maxMemory and Runtim
  • 如何在 Firebase 远程配置中从 JSON 获取值

    我是 Android 应用开发和 Firebase 的新手 我想知道如何获取存储在 Firebase 远程配置中的 JSONArray 文件中的值 String 和 Int 我使用 Firebase Remote Config 的最终目标是
  • 使用 Ant 将非代码资源添加到 jar 文件

    我正在将 java 应用程序打包成 jar 文件 我正在使用 ant 和 eclipse 我实际上需要在 jar 中直接在根文件夹下包含几个单独的非代码文件 xml 和 txt 文件 而不是与代码位于同一位置 我正在尝试使用includes
  • 打印星号的 ASCII 菱形

    我的程序打印出这样的钻石 但只有当参数或菱形的每一面为4 例如如果我输入6 底部三角形的间距是错误的 我一直在试图找出答案 当参数改变时 底部的三角形不会改变 只有顶部的三角形会改变 它只适用于输入4 public static void
  • 在 Wildfly 中与 war 部署共享 util jar 文件

    假设我有一个名为 util jar 的 jar 文件 该 jar 文件主要包含 JPA 实体和一些 util 类 无 EJB 如何使这个 jar 可用于 Wildfly 中部署的所有 war 无需将 jar 放置在 war 的 WEB IN
  • 大数据使用什么数据结构

    我有一个包含一百万行的 Excel 工作表 每行有 100 列 每行代表一个具有 100 个属性的类的实例 列值是这些属性的值 哪种数据结构最适合在这里使用来存储数百万个数据实例 Thanks 这实际上取决于您需要如何访问这些数据以及您想要
  • 如何将 Mat (opencv) 转换为 INDArray (DL4J)?

    我希望任何人都可以帮助我解决这个任务 我正在处理一些图像分类并尝试将 OpenCv 3 2 0 和 DL4J 结合起来 我知道DL4J也包含Opencv 但我认为它没什么用 谁能帮我 如何转换成 INDArray 我尝试阅读一些问题here
  • Kotlin 未解决的参考:CLI 上 gradle 的 println

    放一个printlnkotlin 函数返回之前的语句会崩溃 堆栈跟踪 thufir dur NetBeansProjects kotlin thufir dur NetBeansProjects kotlin gradle clean bu
  • 是否可以通过编程方式查找 logback 日志文件?

    自动附加日志文件以支持电子邮件会很有用 我可以以编程方式设置路径 如以编程方式设置 Logback Appender 路径 https stackoverflow com questions 3803184 setting logback
  • 如何检测 Java 字符串中的 unicode 字符?

    假设我有一个包含 的字符串 我如何找到所有这些 un icode 字符 我应该测试他们的代码吗 我该怎么做呢 例如 给定字符串 A X 我想将其转换为 AYXY 我想对其他 unicode 字符做同样的事情 并且我不想将它们存储在某种翻译映
  • 使用 Guice 优化注册表

    你好 今天思考了一种优化 有一些疑问 语境 我正在使用 Guice 2 进行 Java 开发 在我的网络应用程序中 我有一个转换器注册表 可以即时转换为某种类型 转换器描述如下 public class StringToBoolean im
  • 生成的序列以 1 开头,而不是注释中设置的 1000

    我想请求一些有关 Hibernate 创建的数据库序列的帮助 我有这个注释 下面的代码 在我的实体类中 以便为合作伙伴表提供单独的序列 我希望序列以 1000 开头 因为我在部署期间使用 import sql 将测试数据插入数据库 并且我希
  • Java Swing For mac 中的 DJ Native Swing 浏览器

    我有一个用 Swing 制作的 Java 应用程序 并且使用了一个 DJ Native Swing 浏览器 当我尝试在 OS X 上使用它时 它抛出了一个NoClassDefFoundError尽管我添加了 swt jar 但始终如此 有人
  • GWT 2.3 开发模式 - 托管模式 JSP 编译似乎不使用 java 1.5 兼容性

    无法编译 JSP 类 生成的 servlet 错误 DefaultMessage 上次更新 0 日期 中 0 时间 HH mm ss z 语法 错误 注释仅在源级别为 1 5 时可用 在尝试以开发模式在 Web 浏览器中打开我的 gwt 模
  • 使用布尔值进行冒泡排序以确定数组是否已排序

    我有以下用于冒泡排序的代码 但它根本不排序 如果我删除布尔值那么它工作正常 我知道 由于我的 a 0 小于所有其他元素 因此没有执行交换 任何人都可以帮助我解决这个问题 package com sample public class Bub
  • JMenu 中的文本居中

    好吧 我一直在网上寻找有关此问题的帮助 但我尝试的任何方法似乎都不起作用 我想让所有菜单文本都集中在菜单按钮上 当我使用setHorizontalTextPosition JMenu CENTER 没有变化 事实上 无论我使用什么常量 菜单
  • Java Swing:需要一个高质量的带有复选框的开发 JTree

    我一直在寻找一个 Tree 实现 其中包含复选框 其中 当您选择一个节点时 树中的所有后继节点都会被自动选择 当您取消选择一个节点时 树中其所有后继节点都会自动取消选择 当已经选择了父节点 并且从其后继之一中删除了选择时 节点颜色将发生变化
  • Resteasy 可以查看 JAX-RS 方法的参数类型吗?

    我们使用 Resteasy 3 0 9 作为 JAX RS Web 服务 最近切换到 3 0 19 我们开始看到很多RESTEASY002142 Multiple resource methods match request警告 例如 我们
  • 如何使用play框架上传多个文件?

    我在用play framework 2 1 2 使用java我正在创建视图来上传多个文件 我的代码在这里 form action routes upload up enctype gt multipart form data
  • org.apache.commons.net.io.CopyStreamException:复制时捕获 IOException

    我正在尝试使用以下方法中的代码将在我的服务器中创建的一些文件复制到 FTP 但奇怪的是我随机地低于错误 我无法弄清楚发生了什么 Exception org apache commons net io CopyStreamException

随机推荐