Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Editing a native method class with javassist?

Tags:

java

javassist

With Javassist, is there any way to inject code into a native method? In this case, I'm trying to make the OpenGL calls in my game print out their names and values when called, but all my attempts have hit errors when I assume the openGL dll code is added.

The method would look something like:

public static native void glEnable(int paramInt);

Since the methods initially have no body, the only way I've found to actually add the code is with something like:

CtBehavior method = cl.getDeclaredBehaviors()[0];
method.setBody("System.out.println(\"Called.\");");

The injection itself works, but then the system fails once the library is loaded saying that the method already has code.

I'd rather not use any premade tools for the call tracking, because of the way I need to format and print out the list for the user. Is there any way to handle this? If not, is there some way to find all calls to an OpenGL method within another class and append an additional call to a tracker class?

like image 397
Felix Avatar asked Sep 30 '12 18:09

Felix


Video Answer


2 Answers

I know it is a little offtopic (2 years later), but if somebody was interested, I think it can be done with setNativeMethodPrefix() method and adequate bytecode transformation.

like image 86
zerocool Avatar answered Oct 30 '22 23:10

zerocool


With Javassist, is there any way to inject code into a native method?

Never tried it, but I am not surprised it does not work. Native code is - native. It's a bunch of platform specific bits that bears no relation to Java byte code. And Javassist is all about Java byte code.

Have you consider using proxy based AOP? Check out http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies

I'm not recommending you actually use Spring in your program but it might give you some ideas on how to approach the problem. The reason I think proxy-based AOP might work for you is that you leave your OpenGL based class alone and it just uses the normal native methods. You generate a proxy class which is pure Java but has the same methods as your original class. You call methods on the proxy class which contain the desired call tracking code, plus the invocation of the corresponding method on the "plain object" with it's native methods.

The documentation in Spring says they use JDK dynamic proxies or CGLIB under the covers. So ... I'm thinking that you could use one of these technologies directly as a replacement for your javassist solution.

Hope this helps.

[update]

In the text above I thought you were talking about a class written by you which had primarily instance methods. If you are talking about wrapping the entire OpenGL API, which is primarily static methods, then the AOP proxy method is less appealing. How bad do you want to do this? You could:

  • create a custom class - a singleton class with a factory method. Your singleton class wraps the entire OpenGL API. No logging/tracking code. Just naked calls to the API.
  • modify every single call in your entire app to use your wrapper, instead of calling OpenGL directly

At this point you have an application that works exactly like what you have now.

Now enhance the factory method of your singleton class to return either the bare-bones instance which does nothing except OpenGL calls, or it can return a CGLIB generated proxy which logs every method. Now your app can run in either production mode (fast) or tracking mode depending on some config setting.

And I totally get it if you want to give this up and move on :)

like image 32
Guido Simone Avatar answered Oct 30 '22 22:10

Guido Simone