使用Haskell将函数注入Java .class文件

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

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

“在执行方法之前输入[此处的方法名称] ”,和

执行方法后“ 退出[此处的方法名称] ”。

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

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

那么,这就是各种字节码工程库为您提供的。 ASM,BCEL等。您的家庭作业的细节是一个方面 ,而AspectJ就是这样做的。

听起来像家庭作业是写一个Haskell字节码工程练习,所以你需要自己修改类文件。 @biziclop上面的建议是正确的。 在类文件之前和之后执行操作,记下增量,并自己从Haskell执行相同的操作。

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

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

熟悉后,请逐步进行操作。

  1. 在要检测的java文件中的某处添加System.out.println()调用。 这样可以处理常量池。 编写查找相关常量的Haskell代码并注入字节码。
  2. 从java文件中删除“拐杖”调用,并在Haskell中实现常量池操作。

只需抓住你的Java字节码列表,弹出一个简单的编译类,只需要调用System.out.println(),然后看看。 无论您需要什么方法,都要这样做。 找到这个的最好方法是使用一些简单的代码文件和逆向工程进行一些调查。 您必须将所需的消息转换为unicode并将其传递给您的函数。 不要忘记那部分。 有各种程序可以帮助您克服字节码。

我认为解决此问题的最佳方法是使用Javassist库( Java Programming Assistant )。 Javassist.bytecode类有一些可能有用的函数。