7

我使用 Haskell 编写了一个 Java 字节码解析器,它工作得很好。然而,下一步让我完全难住了。

我的 Haskell 程序需要修改 .class 文件,以便在执行时 Java 程序打印:

Entering [method name here] ” 在执行方法之前,以及

Exiting [method name here] ”在执行一个方法后。

我所知道的是,我们需要在常量池和方法表中附加对 的调用System.out.println,但我觉得我仍然缺少一些东西。

  • 解决这个问题的最佳方法是什么?
  • 你怎么知道如何调用System.out.println字节码?
  • 您如何存储带有方法名称的字符串,以便稍后作为 的参数调用System.out.println
4

4 回答 4

2

可能最简单的方法是编写一个 Java 类,它有一个带有System.out.println()代码的方法,编译它javac并观察结果。

熟悉之后,一步一步来。

  1. System.out.println()在要检测的 java 文件中的某处添加调用。这会处理常量池。编写查找相关常量并注入字节码的 Haskell 代码。
  2. 从 java 文件中删除“拐杖”调用并在 Haskell 中实现常量池操作。
于 2012-04-20T21:03:41.247 回答
2

嗯,这就是各种字节码工程库给你的。ASM、BCEL 等。你的作业的细节是一个方面,而 AspectJ 正是这样做的。

听起来家庭作业是写一个 Haskell 字节码工程练习,所以你需要自己修改类文件。@biziclop 上面的建议是正确的。在类文件上做之前和之后,注意增量,并在 Haskell 中自己做同样的事情。

[ps:当然,上面的“捷径” :P 是如果您不想阅读 JVM 规范(如对您的 q 的评论中所指出的那样)并弄清楚如何去做,就像编写一个Java 编译器。您基本上通过使用各种字节码之一进行调用来调用方法——这里是接口方法调用——在此之前,您需要有接收者,例如 System 类之外的静态字段和堆栈上的方法名称。规格中的详细信息。]

于 2012-04-20T21:11:49.920 回答
2

只需获取您的 Java 字节码列表并弹出一个简单的编译类,并调用 System.out.println() 并查看一下。为您需要的任何方法执行此操作。找出这一点的最佳方法是使用一些简单的代码文件进行一些调查,并在进行过程中进行逆向工程。您必须将所需的消息翻译成 unicode 并将其传递给您的函数。也不要忘记那部分。有各种程序可以帮助您征服字节码。

于 2012-04-20T21:24:08.247 回答
0

我认为解决这个问题的最好方法是使用Javassist库(Java Programming Assistant)。 Javassist.bytecode类有一些可能有用的功能。

于 2012-05-13T06:15:26.413 回答