Latest Posts »
Latest Comments »
Popular Posts »

Hacking with IDE plugins – fun art of binary patching

Written by Toomas Römer on December 11, 2009 – 6:34 pm

Today’s software is so much about integration. You can have a cool Java utility but if you don’t have an Eclipse plugin for that, a large % of Eclipse users won’t adopt (IDEA & NetBeans users require plugins just as much). In the consumer market the same goes for browser extensions and iPhone apps that support the main service with better accessibility.

There are different ways for integration. Usually it is done via an API. The host platform offers some hooks into the system and you can use them to add some custom functionality on top of the host (or maybe just integrate your own product with the host). The result of this in the IDE world is a plugin. JRebel (the product our team is spending the most development time on) has plugins for application servers, frameworks and even IDEs.

If you’re in luck you can achieve everything with the API, if not you need other tricks. If the API does not offer certain public methods or access to some internal fields you can go in with reflection and still use them (of course there are no guarantees if the internals stay the same on version changes).

One step further to the darkside is binary patching. By binary patching I mean adding/changing/removing methods/fields/classes in runtime. This is the approach that we had to take when writing the JRebel NetBeans plugin.

On NetBeans startup we lookup a debugger class and on success try to patch it. In 2009 and using the JVM (not native apps) it is quite an easy task, at least for the most part. No assembler involved (of course you could be using a bytecode generation library), no need to do jumps to correct offsets or even read assembler (or bytecode).

In our case we use the Javassist library. It is a matter of inserting Java code embedded into a String to methods looked up via reflection. For example the following code adds some new code into the beginning of a method.

ctc.getDeclaredMethod("setRequests").insertAfter(
  "org.netbeans.api.debugger.jpda.LineBreakpoint _breakpoint = getBreakpoint();" +
  "java.lang.String _className = _breakpoint.getPreferredClassName();" +
  "if (_className == null) {" +
  "  _className = reader.findCachedClassName(_breakpoint);" +
  "  if (_className == null) {" +
  "    _className = org.netbeans.modules.debugger.jpda.EditorContextBridge.getContext().getClassName (" +
  "      _breakpoint.getURL ()," +
  "      lineNumber);" +
  "    if (_className != null && _className.length() > 0) {" +
  "      reader.storeCachedClassName(_breakpoint, _className);" +
  "    }" +
  "  }" +
  "}"

For the complete source code of the patch see the src folder of the nb-plugin.

In conclusion, the best way to integrate with any system is via the API it provides. If it does not cut it then look into reflection and start using internals. You will lose on maintainability of course. Still not happy? Look into binary patching and have your fingers crossed whenever the target platform releases a new version.

Reblog this post [with Zemanta]

Tags: , , ,
Posted in cool, tips | 1 Comment »

Netbeans – running programs the easy way

Written by Toomas Römer on March 31, 2009 – 3:10 pm

I have not been so angry at an IDE for a while, arrrrrrrghhh, rant follows.

How hard can it be to add JVM arguments to the run configuration of an application when running it from an IDE? Lets say I want to add -Dsuperboost=true or just ~/myconf/.myconf to the Java application?

Eclipse has a green button and Run configurations under it, there you can specify Program arguments and VM arguments. Easy.

IntelliJ Idea has a green button and Edit Configurations under it, there you can specify Program parameters and VM parameters. Easy.

Netbeans has a green button. Thats it. Where are the options? When you check project Properties there is Build » Compiling & Packaging but no run. Googling for such a generic topic does not help me much, just aggrevates more.

Finally I realize, everything is ANT based, I’ll just modify the build.xml files used. The toplevel build.xml includes project/nbproject/build-impl.xml, this includes some NetBeans bundled build.xml. Okay, this is not the best place.

I find a file named project.properties with two options in it, javac.compilerargs and javac.source. Jackpot, I’ve found the hidden settings, I just need to figure out the magic names that I could add. Some more googling and trying out different flags from different NetBeans versions I’m still out of luck, I’m unable to guess the names.

Finally I went through NetBeans/harness/build.xml » common.xml » run.xml and the magic secret hidden flags follow:

  • run.jdkhome
  • run.args.common
  • run.args.prepared
  • run.args
  • run.args.extra

Weeehah! Now I need only to add “-noverify”. No, more like “-J-Xverify:none”, argghh.


Tags:
Posted in rant | 9 Comments »