Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the Java Instrumentation API to reload classes when they change on the the file system?

  • I don't want to use the URL Classloader to load classes.
  • I want to implement this myself.
  • I don't want to use a solution like JRebel (although it's great).

I've got prior experience of JavaAssist, bytecode generation, implementing javaagent class transformers etc.

I would like to write a javaagent which hooks into the classloader or defines it's own system classloader.

I'll store the class files in an in memory cache, and for particular files, periodically reload them from disk.

I'd prefer to do this in a way which doesn't involve continuously polling the file system and manually invalidating specific classes. I'd much rather intercept class loading events.

I last messed around with this stuff 4 years ago, and I'm sure, although my memory may deceive me that it was possible to do, but 8 hours of searching google doesn't present an obvious solution beyond building a patched JVM.

Is this actually possible?

I've created a stub implementation at https://github.com/packetops/poc_agent if anyone's interested in a simple example of javaagent use.

update

Just found this post - I may have been using the wrong approach, I'll investigate further.

like image 589
bryan hunt Avatar asked Feb 04 '26 18:02

bryan hunt


1 Answers

It depends on what you want to do. If you want to reload your classes and define new ones, then you are fine with implementing your own classloader, as you already found.

If you want to replace existing classes, things become more "envolved". You can do this by implementing your own tiny Java agent. See the Java documentation, how to do this: http://docs.oracle.com/javase/7/docs/api/java/lang/instrument/package-summary.html

With the instrumentation mechanism you can not freely redefine classes, quote from Instrumentation.redefineClass:

The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance. These restrictions maybe be lifted in future versions. The class file bytes are not checked, verified and installed until after the transformations have been applied, if the resultant bytes are in error this method will throw an exception.

If you want to do more, you need to load it again. This can be done under the same name, by using a different classloader. The previous class definition will be unloaded, if no one else is using it any more. So, you need to reload any class that uses your previous class also. Utlimatly, you end up reinventing something like OSGi. Take a look at: Unloading classes in java?

like image 151
cruftex Avatar answered Feb 06 '26 08:02

cruftex



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!