当前位置: 首页 > 面试题库 >

在Javassist中修改行号

施自明
2023-03-14
问题内容

所以最近我一直在使用Javassist,但遇到了一个我找不到答案的问题。CtMethod的insertAt方法允许您在特定的行号处插入代码,但是它会覆盖该行还是保留该行,我该如何使其与默认行相反?我有一个应用程序,可以在运行时使用Javassist修改源,该源基于XML文件中的“挂钩”。我要使它可以覆盖一条线,或者可以将一条线放置在该线的上方而不是覆盖它。显然,有很多方法可以做到这一点,但是我宁愿使用一种正确的方法。


问题答案:

容易的部分

CtMethod对象中存在的方法insertAt(int lineNumber,String
src)
允许在给定行中的代码
之前* 注入以 src 编写的代码。 *

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

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表示形式):

   // 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没有提供简单的方法来删除一行代码,因此,如果您真的想替换它,那么除了破解之外,别无选择。

怎么做?好吧,让我向您介绍您的新朋友(如果您还不知道)CodeAttribute对象。

CodeAttribute对象负责保存表示方法流的字节码,该代码属性还具有另一个名为LineNumberAttribute的属性,该属性可帮助您将行号映射到字节码数组中。因此,总结该对象即可满足您的所有需求!

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

再一次,method是方法 print 的CtMethod表示形式 __

    // 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;
    }

原始 TestSubject类中运行此修改,将导致注入的类具有以下输出:

 one
 three

加起来

当你有需要添加一条线,仍保持现有的一个,你只需要使用给出的例子 比较容易的部分 ,如果你想更换线路,您必须先删除使用中给出的例子既有线 的硬部分
,然后使用第一个示例注入新行。

还请记住,在示例中,我假设您已经对javassist的基础知识感到满意,只显示了多汁的部分,而不是全部内容。这就是为什么,例如,在示例中没有ctClass.writeFile
…您仍然需要这样做,我只是省略了它,因为我希望您应该知道您必须这样做。

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



 类似资料:
  • 问题内容: 我有一些人已经解决过的问题,但问题是我不了解我的实现中缺少什么。 我的hibernate代码的一部分如下: 问题是我想通过更改hibernate.connection.url属性中的“数据库”一词来选择要在运行时中使用的数据库。 在javaswing中,我正在实现此功能: } 然后,我用按钮检查所做的更改,从组合框中选择所需的数据库: 现在,debug1的输出正在更改,因此我在此打印中

  • Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京技术学院的数学和计算机科学系的 Shigeru Chiba 所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态AOP框架。 Javassist(JAVA 编程ASSISTant)使Java字节码操作变得简单。 它是一个用Java编辑字节码的类库; 它使Jav

  • 我在Spring框架中使用ehcache。我正在使用ehcache.xml初始化ehcache。然而,我想在运行时添加某些属性,如terracottaconfig。为此,我覆盖了类EhCacheManagerFactoryBean。目前,我正在覆盖这个类的方法getObject()(我不知道这是否是一个正确的覆盖,因为在使用ehcache.xml文件初始化类之前,调用了其他方法setResourc

  • 修改矩形和圆角矩形 您可以调整矩形的大小和位置。在 Photoshop 中,您也可以在绘制圆角矩形形状后,对这些形状的角半径进行修改。可单独调整每个圆角,并可以同时对多个图层上的矩形进行调整。 注意:如果您选择多个矩形,则最上面矩形的值将显示在“属性”面板中。您键入的值将应用于所有选择的矩形。 使用“路径选择工具”可选择一个或多个矩形或圆角矩形。 要更改矩形的尺寸,请在“属性”面板或选项栏中的 W

  • 接口说明 如果已创建了飞行路径,而想修改飞行路径的相关信息,Wish3DEarth团队新增了修改飞行路线的接口,开发者可以通过该接口,来修改飞行路径的相关信息(名称、视点等)。 注意:vpIds如果不传,默认会将原有的视点置空 如需调用,请访问 开发者文档 来查看详细的接口使用说明 该接口仅开放给已获取SDK的开发者 API地址 POST /api/flyline/1.0.0/update 是否需

  • 问题内容: 我正在尝试制作一个包含名称的列表。该列表应该是可修改的(添加,删除,排序等)。但是,每当我尝试更改ArrayAdapter中的项目时,程序都会崩溃,并显示错误。这是我的代码: 我尝试插入,删除和清除方法,但没有一个起作用。有人可以告诉我我做错了什么吗? 问题答案: 我自己尝试了一下…发现它没有用。所以我检查了ArrayAdapter的源代码并发现了问题。由数组初始化后,将其转换为不能修