I've been a zone leader with DZone since 2008, and I'm crazy about community. Every day I get to work with the best that JavaScript, HTML5, Android and iOS has to offer, creating apps that truly make at difference, as principal front-end architect at Avego. James is a DZone Zone Leader and has posted 639 posts at DZone. You can read more from them at their website. View Full User Profile

How JavaRebel Saves Development Time

11.03.2009
| 9895 views |
  • submit to reddit

JavaRebel has been around for quite some time now. I heard about it last year, and was hooked by the statement that it could cut development time by 6%.  It’s a brave statement for any tool to make, so I had to find out more. It’s only recently that I’ve put aside the time to try this tool out and find how it actually saves me time. Before I go into this in detail, let’s see why there’s a need for productivity tools with the current Java environments.

Recently I’ve been working on a Java EE project, where I develop the project in Eclipse 3.5 and have set up Tomcat v6 as my server. It works pretty well, any changes I make while coding my JSPs get to the server pretty quickly. However, if I make a change to any of the backing beans I need to redeploy properly, not being able to rely on the default mechanism that works so well for my JSPs.  How long does this redeploy take - maybe about a minute, sometimes slightly longer. The thing about this project in particular is that I’m doing it in my spare time, which I don’t have a whole lot of – those minutes I spend restarting are quite valuable to me when you add them all together.

As a desktop developer, this pattern is familiar to me. When debugging through my code in Eclipse, it’s nice to make a change and see that reflected in the running instance straight away with HotSwap. Sometimes I want to make more fundamental changes like changing the class structure, and when I do that I know I’m going to have to stop my debug instance and start again. When you’ve gone through a long series of steps to get here, this can be a killer.  Without a doubt, this is one of the reasons that we fail when it comes to the “quality code vs code on time” question.  I’ve often wondered why this is the case with Java when dynamic languages and .NET can handle this quickly. 

Rather than give up on my language of choice and move to .NET, I’d prefer that this gets fixed for my current environment.

While there are some partial solutions available without the need for something like JavaRebel, they don't go far enough. Hot Deploy, for example, allows you to redeploy your code to an application server in about 30 seconds. That's not bad, but JavaRebel allos you to do this reload in milliseconds. HotSwap is another good solution, allowing you to change code during a debugging session but it doesn't allow major structural changes such as adding new classes or methods. Finally, OSGi is another approach to take - by splitting your application into smaller modules, it can make the redeployment seem faster.

On the face of it JavaRebel seems to be the answer to all my problems here.  JavaRebel is just a nice clean addition to your JVM or application server on the class loader level.  With JavaRebel, it’s conceivable that I can start up my debug session and nicely interweave my code changes into the running instance, without anything unexpected happening. How does this work? Well the FAQ describes it as follows:
When a class is loaded JavaRebel will try to find a corresponding .class file for it. It will search from the classpath (including an application classpath, like WEB-INF/classes) and from the places specified in the rebel.xml configuration file. If it find a .class file JavaRebel instruments the loaded class and associates it with the found .class file. The .class file timestamp is then monitored for changes in the loaded class and updates are propagated through the extended class loader, to your application.
JavaRebel can also monitor .class files in JARs if they are specified in rebel.xml.


But the main piece to the jigsaw is:

Importantly, when loading updates to a class, JavaRebel preserves all of the existing instances of that class. This allows the application to just continue working, but also means that when adding a new instance field it will not be initialized in the existing instances, since the constructor will not be rerun.

I’m intrigued by how this works, so I contacted some of the developers at the JavaRebel team to find out more. 

DZone: Great product guys. How long has JavaRebel been around?

Jevgeni Kabanov: We started development of the prototype in January 2007 and had the first internal alpha running in March. The public didn’t see it before 1.0 M2 beta, which started in October with TheServerSide and DZone announcements. The initial response was quite overwhelming and by December we fixed everything we could and released 1.0 GA. So depending on what date you pick we are either over 2 years old or just about to hit that date.

DZone: Why doesn’t this exist already in Java? And how has .NET managed to have this from day one?

Jevgeni Kabanov:  This are actually two quite related questions and I’d start with the second one.
I’m not a .NET expert, but as far as I understood from looking into this and asking around, .NET doesn’t have such functionality either. The tricky part in reloading object-oriented code is preserving the object state intact. As far as I can tell .NET does not do that (e.g. in a desktop application you have to close it and navigate from scratch to see the change). However web development frameworks in .NET are designed around stateless and/or isolated classes so turnaround is usually instantaneous. However I’d assume that writing a complicated business app would run into same problem as Java at some point. Of course if there’s some .NET expert could prove me wrong, I’d only feel happy for the platform.

This also makes the reasons why this doesn’t exist in Java clearer. But the main reason, besides being plain tricky to implement, is that Java focuses heavily on performance. The need to support class code, structure and layout changes would mean significant compromises in the JVM Just-In-Time compiler. Specifically you’d have to do dependency analysis between classes and make the method lookup and calls more dynamic than they currently are. This would decrease performance, or at least further complicate the design of the JVM. These compromises are already present in dynamic languages VMs, which makes it easy to implement such features there.

DZone: Without giving away too many of your secrets, how is something like this done with Java?

Jevgeni Kabanov:  We are actually doing at least three different things:

  1. Map the project workspace to the deployed WAR/EAR on the server so that the changes to classes and resources in the workspace would be immediately visible to the running application.
  2. Reload classes in the running JVM when the underlying .class files change.
  3. Integrate with various frameworks like Spring to make sure the changes to classes and resources are reinterpreted (e.g. new Spring dependencies are injected).

To do the first one we integrate with each application container separately. We extend their APIs with an ability to inject and override classes, resources and web resources in the running web applications. We then interpret the rebel.xml file provided by the user to override the deployed classes and resources with the ones found from the project workspace. The integration part is actually open sourced and is available from our repository for anyone interested.

To reload the actual classes we build a kind of our own Just-In-Time compiler, which intercepts loading of every class and rewrites them in a way that makes reloading possible. This involves some techniques taken from the dynamic languages virtual machines, though to make it all run fast enough on the JVM we had to do a lot of R&D.

Finally we have a plugin system with specific plugins for specific frameworks. The plugins are written in an Aspect-Oriented way (even though for performance and size reasons we use a low-level Javassist framework). Each plugin provides a Reloading aspect for a particular framework.

DZone:  Could you take us through some instructions for adding JavaRebel to my development environment – either Eclipse or NetBeans?

Jevgeni Kabanov: If you use Eclipse and run the server from inside the Servers view the installation will be quite trivial. All you have to do is download JRebel distribution and install the JRebel Eclipse plugin from the Eclipse update manager. As soon as you’ve done that you’ll have a “Run with JRebel agent” in the launch configuration of all your applications and servers. Also you’ll get a “Generate rebel.xml” popup menu item if you right-click a project. Saving it to a source folder is all you need to let JRebel know your project layout. The plugin for IntelliJ IDEA has also just been released and Netbeans support is in the works. If you use Maven, we can also generate the rebel.xml file during build with a Maven plugin.
However if you run a standalone server or your setup is unusual you’ll have to do some configuration by hand. It’s described in the installation manual in three easy steps. We have also begun to release specific setup guides beginning with Apache Tomcat .

DZone: What features are you adding to JavaRebel at the moment?

Jevgeni Kabanov: The big things to look for in the next release are integration with EJB containers supporting changes to EJB interfaces, full Struts 1.x and 2.x support, better support for enums and static values plus some stuff we’d like to keep secret for the moment :)

If you’re not convinced, the ZeroTurnaround site outlines how much development time you can save with the Business Value Calculator. And Jevgeni offers a full refund to anyone who doesn’t see JavaRebel pay for itself within a month.
 

Comments

Dave Booth replied on Tue, 2009/11/03 - 5:58am

Quick note - the name "JavaRebel" has been changed to "JRebel"

http://www.zeroturnaround.com/blog/community-renames-javarebel-to-jrebel/

 

Sumit Sengar replied on Tue, 2009/11/03 - 8:48am

I have been using a licensed version of Java rebel since last few months and have witnessed a tremendous boost in the development productivity. It is a great tool. My application runs on weblogic, and I use the following configuration in startWeblogic.cmd to get rebel working.

 set JAVA_OPTIONS=-noverify -javaagent:C:\jrebel-2.1a\jrebel.jar  -Drebel.dirs=C:\<codeBase>\bin %JAVA_OPTIONS%

 Note : I am using an exploded directory deployment format. For achive based deplyments, a rebel.xml is needed

Naiden Gochev replied on Tue, 2009/11/03 - 10:42am

If you are working on web application I can say :

Just install Glassfish v3 and you dont need JRebel.

:) 

Andy Gibson replied on Tue, 2009/11/03 - 1:02pm

+1 for Glassfish v3 - I was blown away by the way it redeploys modified code (EJB and Pojos) in both Eclipse and Netbeans just by using it the same way you would use any server in those IDEs. Amazing Stuff.

 

Mike P(Okidoky) replied on Tue, 2009/11/03 - 1:16pm in response to: Naiden Gochev

But what about instance data? When you're writing a feature of an application that needs a login, and a bunch of data to be filled out before you can test that feature you're working on, not having JRebel and only using J2EE redeployment, you'd have to redo all that every time you change the code, right?

Jevgeni Kabanov replied on Tue, 2009/11/03 - 1:24pm in response to: Naiden Gochev

GlassFish v3 just starts up faster, you still have to wait for your project to initialize. And any large project will take its time, whatever the container. On the applications that are usually used to show it any container would do great.

Andy Gibson replied on Tue, 2009/11/03 - 1:50pm in response to: Mike P(Okidoky)

Glassfish will preserve session state across redeployments, here is a link showing it in action in a similar situation you are talking about.

 

 

Mike P(Okidoky) replied on Tue, 2009/11/03 - 2:36pm in response to: Andy Gibson

 Thanks for the link.

But wouldn't the only information that gets persisted are serializable (sub)components in the session? In non trivial applications there has to be situations where not everything is/can preserved in a swap-out swap-in mechanism?

Arbi Sookazian replied on Wed, 2009/11/04 - 11:11am

How does JRebel compare to the special Seam classloader? Is there any added value to using JRebel in a Seam project (if possible)? Also, AFAIK it's not possible with the current version of JRebel to make signature changes or add methods, for example to local interfaces in EJBs. I believe it has to do with the dynamically generated proxies by the EJB container? That is something they're obviously adding in future versions. And that would perhaps allow incremental hot deployment of EJB (SLSB/SFSB) modifications/additions, etc. in Seam apps? This is one of the reasons why so many Seam community members are using WAR instead of EAR (i.e. no EJBs and just POJOs for business logic components) in order to facilitate hot incremental deployment with Seam classloader.

Arbi Sookazian replied on Wed, 2009/11/04 - 11:13am

Also, are there any plans to support hot deployment of changes to the Seam components.xml file? I noticed that in JRebel 2.1a struts-config.xml and applicationContext.xml are supported.

Jevgeni Kabanov replied on Fri, 2009/11/06 - 9:40am

@rabies There are definitely plans to support Seam configuration changes, but it hangs on the extended support for EJBs that is planned for the 3.0.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.