Inject a function into a Java .class file using Haskell

爱⌒轻易说出口 提交于 2019-12-09 10:53:59

问题


I have written a Java bytecode parser using Haskell, and it works just fine. However the next step has me completely stumped.

My Haskell program needs to modify the .class file so that, when executed, the Java program prints:

"Entering [method name here]" before executing a method, and

"Exiting [method name here]" after executing a method.

All I know is that we will need to append the constant pool and method table with calls to System.out.println, but I feel I'm still missing something.

  • What is the best way to approach this problem?
  • How do you know how to call System.out.println in bytecode?
  • How do you store the string with the name of the method, to later be called as an argument of System.out.println?

回答1:


Well, this is what the various byte code engineering libraries give you. ASM, BCEL, etc. The specifics of your homework is an aspect, and AspectJ does precisely that.

Sounds like the homework is to write a Haskell byte code engineering exercise, so you will need to mod the class file yourself. Suggestion above by @biziclop is correct. Do a before and after on a class file, note the delta, and do the same yourself from Haskell.

[ps: of course, the above "short-cut" :P is if you don't feel like reading the JVM Spec (as noted in comment to your q) and figuring out how to do it as if you would if writing a Java compiler. You basically call a method by using one of the various byte codes for invoke -- here an interface method call --before which you need to have the receiver e.g. static field out of class System and the method name on the stack. Details in the spec.]




回答2:


Probably the easiest approach is to write a Java class that has a single method with a System.out.println() code in it, compile it with javac and observe the results.

Once you are familiar with it, proceed step by step.

  1. Add a System.out.println() call somewhere in the java file that you want to instrument. This takes care of the constant pool. Write the Haskell code that finds the relevant constants and injects the bytecode.
  2. Remove the "crutch" call from the java file and implement the constant pool manipulation in Haskell.



回答3:


Just grab your Java bytecode listing and pop open a simple compiled class with a function call to just System.out.println() and take a peek. Do this for whatever methods you need. The best way to find this out is to do some investigation with some simple code files and reverse engineer as you go along. You'll have to translate the message you want into unicode and pass that into your function. Don't forget about that part as well. There are various programs that will help you on your quest to conquer the bytecode.




回答4:


I think the best way to approach this problem is to use the Javassist library (Java Programming Assistant). Javassist.bytecode class has some functions that might be useful.



来源:https://stackoverflow.com/questions/10253474/inject-a-function-into-a-java-class-file-using-haskell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!