Blog

This is a story of an interesting support request handled by our guru Lauri Tulmin. The inquiry was about a rare occurring ArrayIndexOutOfBoundsException that JRebel seemed to cause in Wicket. After some investigation he discovered that the root exception was thrown from the following Wicket code:

private final Map<imodifiable, Entry> modifiableToEntry =
   new ConcurrentHashMap();
 
  public void start(Duration pollFrequency) {
    this.task = new Task("ModificationWatcher");
 
    this.task.run(pollFrequency, new ICode() {
      public void run(Logger log) {
        Iterator iter = new ArrayList(
          ModificationWatcher.this.modifiableToEntry.values()).iterator();
        while (iter.hasNext())

Specifically the exception was thrown from the constructor of ArrayList. How was that possible?

Let’s take a step back and review the reasons for this code. One issue with collections is that when iterating a ConcurrentModificationException is thrown if a collection is changed (usually by a different thread). This is done to protect the Iterator from unpredictable behaviour. A common idiom to avoid it is to copy the collection before iteration like that:

for(Iterator i = new ArrayList(collection).iterator(); i.hasNext();) {...}

Note that the collection must either to be synchronized or otherwise suitable for a multi-threaded environment.

This idiom is a very common one, as easily proven by a simple Google Code search. In fact we used it several times in the JRebel code and is present in several places in Wicket as well. So how could this cause an ArrayIndexOutOfBoundsException?

When Lauri investigated in depth he found out that this idiom is inherently unsafe in a multi-threaded environment (even when the underlying collection is synchronized!). The reason for that is the way ArrayList was constructed before Java 1.6. In my 1.5 Java SDK source code it looks like this:

public ArrayList(Collection<? extends E> collection) {
  int size = collection.size();
  firstIndex = 0;
  array = newElementArray(size + (size / 10));
  collection.toArray(array);
  lastIndex = size;
  modCount = 1;
}

The issue is that there is a race condition between the time the size is recorded and the collection.toArray(array) is called. During that time it is conceivable (and indeed possible) that the size of the collection is changed by a different thread. If the size is now bigger, the array copying in toArray() fails with the dreaded ArrayIndexOutOfBoundsException. When researching the issue further we found that the constructor in Java 1.6 ArrayList has been changed to avoid this issue, so at least on Oracle Java 1.6 or later you are safe. Unfortunately I couldn’t find a specific bug referring to that issue, so likely as not it’s an accidental fix.

So what should you do to avoid this issue? One way is to put the synchronized block around the whole loop, but this requires that you only access that collection from other threads in the same synchronized block. An easier solution is to use the toArray()method like this:

for (Iterator i = Arrays.asList(collection.toArray()).iterator(); i.hasNext();)

This minor release includes a score of improvements across the board. Among the most important is that the Google App Engine support is now out of the beta and Google Web Toolkit support has been substantially improved, and the only reason we still keep it in beta is because we don’t have a full automated test harness for it yet. We have also tested JRebel with Tomcat 7 and Jetty 7.1 and can now declare them officially supported. Beta support for serializing added fields has been added, but is still disabled by default. Please add -Drebel.serialization=true and let us know how it works for you. Also we worked some of our magic with AspectJ and Groovy, so those of you who had issues should definitely upgrade to this version. See full changelog for details, or grab the download!

With the support for all Java EE standards this release of JRebel will help you reach a new level of productivity. Whatever change you make to your code, whether it’s a class, resource, configuration or a component, you can immediately see it in your application, with no need to build or redeploy. Although we’re still waiting on usage stats to confirm it, we estimate that JRebel 3.1 will eliminate up to 95% of builds/redeploys that you have to do without it on a common Java EE project.

The first thing you’ll notice after downloading the new 3.1 release, is the support for reloading JPA entities and configuration on all containers. Hibernate and OpenJPA plugins are now enabled by default, but for TopLink/EclipseLink we’re waiting for more user feedback, so go ahead and fire it up. JRebel also fully support reloading native entities and configuration for Hibernate and TopLink.

The second is the support for EJB interface changes and JSP scriptlet changes in GlassFish. Changes to EJB interfaces and scriptlets are now reloaded instantly on all major containers. New features include a spanking new iBatis plugin, beta support for the Geronimo container and a host of others.

Download it while it’s hot!

The first update to the 3.x line includes better handling of JDK proxies, support for Spring dm Server 2.x, advanced scriptlet support for WebSphere and Resin and more. Remember that the advanced scriptlet support is only available with the Enterprise Add-On, which is a free upgrade for all current users –- as long as you upgrade before June 1st.

Pick up the new version at our download page, with or without the Enterprise Add-On.

This is exciting — Today is the day that we get to announce the culmination of 8 months of development effort, fine-tuning, bug fixing, and, awesome awesome awesome feature-adding (don’t just take our word for it, check out the buzz on Twitter). Today we announce the release of JRebel 3.0!

JRebel has matured a lot with this release. Adding to the ability to reload classes, it now integrates tightly with all common Enterprise stacks, allowing seamless reloading of almost all changes across the board. We’re talking about preventing 100% of your incremental builds and over 90% of the redeploys that you had to do during the day. Keep your focus, stay in flow, and have more fun delivering more features, with less defects, faster — just by taking your time back from an antiquated process.

Here’s the exciting part — the new features:

  • Better Java EE support
    • EJB — JRebel now includes plugins for JBoss (4.x, 5.x), Oracle Weblogic (8.x, 9.x, and 10.x) and IBM WebSphere (6.1 and 7.0) that support changing the Local/Remote EJB interface in EJB 1.x, 2.x and 3.x. It also supports on-the-fly dependency injection for @EJB annotation in JBoss. Unfortunately we don’t support EJB interface changes on IBM WebSphere 6.0 or earlier and require the EJB 3.0 Feature Pack to be installed on IBM WebSphere 6.1, even if you use EJB 1.x or 2.x.
    • JSP <scriptlet>-s — Now when you change your Java code (e.g. add a new class or method) it can be immediately used in the Java code snippets in the JSP.
    • JSF — Plugin for Mojarra that supports changes to configuration and annotations, and other JSF implementations are on the way.
    • CDI — Plugin for Weld that supports changes to annotations.
    • JPA — Plugin for OpenJPA that supports changes to entities and configuration. We’re considering this beta for this release and have it disabled by default. Other JPA implementation are on the way.
  • Framework support
    • Seam — Supports changes to annotations.
    • Hibernate — Supports changes to entities, annotations and configuration. This rocks, but we’re taking it easy and considering it beta. It’s disabled by default.
  • Support for adding static fields and changing enums. Previously when you added a static field to your class you’d see a discouraging warning in the console and get an exception when trying to access the field. Now JRebel will happily print “Reinitialized class” and your application will continue working as if nothing happened. To top it off you can also change Java 1.5 enums in any way you like and they’ll continue working!
  • Startup time improvements. We significantly improved class/resource lookup overhead with caching and better server integration. Our nightly users are reporting up to 2x improvements in startup time.
  • 25%-30% less memory use. It is not uncommon to need a lot of PermGen heap with JRebel enabled, so we optimized memory use and will continue to drive it down in the upcoming milestones.
  • Better Proxy Support JRebel now integrates tightly with Javassist and CgLib, providing much better compatibility with changes to class signature in some advanced cases, e.g. JBoss Seam.
  • rebel.xml Editor. A GUI editor for creating JRebel configuration files is now available and will soon be integrated in the IDEs. This makes it easier to setup your project and get started with JRebel.

We’re also happy to announce the release of the JRebel Enterprise Add-On. It’s meant for larger enterprises working with a more diverse set of applications, and preferences towards more centralized management. It supports older or discontinued technologies, which often require more maintenance and have longer restart & redeploy times. The Enterprise Add-On will be a free upgrade for all current users – as long as you upgrade before June 1st.

You can try JRebel free for 30 days, with or without the Enterprise Add-On from the same place where everyone else gets the new version.. right here! Download JRebel

Say hello to the last release candidate before the final release hits the virtual shelves on Friday — JRebel 3.0 RC2. The changes mostly include fixes, though some features were tweaked as well. Download it now and tell us if there’s anything wrong with it.

We are excited to announce the last milestone on the way to the JRebel 3.0. This release includes the following exciting new features:

  • More EJB Support. JRebel now includes plugins for IBM WebSphere 6.1 and 7.0 that support changing the Local/Remote EJB interface in EJB 1.x, 2.x and 3.x. Unfortunately we don’t support EJB interface changes on IBM WebSphere 6.0 or earlier and require the EJB 3.0 Feature Pack to be installed on IBM WebSphere 6.1 even if you use EJB 1.x or 2.x.
  • Better Proxy Support. JRebel now integrates tightly with Javassist and CgLib, providing much better compatibility with changes to class signature in some advanced cases, e.g. JBoss Seam.
  • Hibernate Plugin. Now when you change your database schema the ORM follows. JRebel will recreate the SessionFactory automatically. Unfortunately this may take some time, so you’ll have to wait for it to finish, but it’s still much faster than a full redeploy.
  • Mojarra JSF Plugin. Supports reloading JSF annotations and XML configuration on the fly.
  • Seam Plugin. Supports reloading the Seam annotations on the fly.
  • Weld Plugin. Supports reloading the Weld annotations on the fly.
  • rebel.xml Editor. A GUI editor for creating the JRebel configuration files is now available and will soon be integrated in the IDEs.
  • We also added support for reloading property resource bundles on IBM JVM, improved startup behaviour to prevent deadlocks and improved expression language support.

In addition to that there are numerous fixes and minor features that you can see in the changelog. And it includes the features introduced in 3.0 M1 and 3.0 M2; in case you forgot, here they are:

  • Advanced EJB Support. JRebel now includes plugins for JBoss 4.x, 5.x and Oracle Weblogic 8.x, 9.x and 10.x that support changing the Local/Remote EJB interface in EJB 1.x, 2.x and 3.x. It also supports on-the-fly dependency injection for @EJB annotation in JBoss. In the coming milestones we’ll add support for IBM WebSphere and more comprehensive support for the EJB 3.x features
  • Startup time improvements. We significantly improved class/resource lookup overhead with caching and better server integration. Our nightly users are reporting up to 2x improvements in startup time.
  • More integration. We added or improved plugins for Guice 2.x, Groovy, Wicket 1.4, Google App Engine, AspectJ, Struts 1 and Spring MVC. With every new plugin we are a step closer to our vision of seamless updates to your application, no matter what are you changing. Expect even more integration in the next JRebel release.
  • Support for adding static fields and changing enums. Previously when you added a static field to your class you’d see a discouraging warning in the console and get an exception when trying to access the field. Now JRebel will happily print “Reinitialized class” and your application will continue working as if nothing happened. To top it off you can also now change Java 1.5 enums in any way you like and they should just continue working. This feature is still a tad experimental, so please help us out to smooth it out!
  • Full JSP <scriptlet> support. Now when you change your Java code (e.g. add a method) it can be immediately used in the Java code snippets in the JSP.
  • 25%-30% less memory use. It is not uncommon to need a lot of PermGen heap with JRebel enabled. Now we optimized the memory use and will continue to drive it down in the upcoming milestones.

Download and enjoy!

Over the Reloading Java Classes (RJC) article series, we’ve examined how class reloading happens, from objects and classloaders to application servers and solutions that reduce Turnaround. It’s been pretty in-depth, so we’d like to take a step back, move to more shallow ground, and take a look at why we would want class reloading to work in the first place. What are the real costs of missing class reloading on Java teams?

As we discover, this is a challenging question to answer — but we’ll give it a shot here, using the attempts of others to guide us.

Other Articles in the Reloading Java Classes Series

The Easily-Measurable Cost of Turnaround: Builds and Redeploys

Last year we ran two surveys asking developers how much time they spend building and redeploying their application. Although we’ve been talking with developers about this for a long time, and everyone understands that some amount of time is spent on builds and redeploys, it was still surprising to see the results – including actual numbers of minutes, days, and weeks spent on the process. For example, during an average hour of coding developers spend:

To be fair, there are large deviations on both sides of these averages — the survey data we used only came from 600 and 1100 respondents respectively, and they used a variety of technologies which you can read about in the reports themselves. Some folks don’t spend as much as the averages, while others spend much more, and your project could be anywhere in that range.

Given that, the averages should apply pretty nicely to Java EE development as an industry (with the usual disclaimer of “lies, damn lies and statistics”). Let’s take a look at an awful scenario — where everyone in the industry is right on the average:

  • Build (6 mins) + Redeploy (10.5 mins) = 16.5 minutes per hour of development or 27.5% of coding time
  • Assuming that developers only code 5 hours per day x 5 days per week x 48 weeks a year = 1200 coding hours a year
  • 1200 hours * 27.5% = 330 hours a year or 330/40 = 8.25 full-time work-weeks a year spent on turnaround, per developer
  • Assuming $20/h average salary, this adds up to 330 * 20 = $6600 per developer per year [Source: conservative estimation backed by http://www.worldsalaries.org/computerprogrammer.shtml]
  • Larry Ellison recently quoted the number of Java developers around the world at 9 million.
  • If you’d like to work out the time or cash spent annually by the industry on Turnaround, these are some numbers you can start with.

Context Switching

Programming is complicated. In fact it’s so complicated that most people are not capable of doing it.  Those who are capable must mentally juggle a lot of context while writing code.. context including specifications, GUI considerations, relevant library calls, relevant application classes, methods and variables and so on.

This information is held in the the working (aka short-term) memory. Since the working memory is not meant for long term storage, switching away from a current task means that you will start losing the context surrounding the code, and then spend time trying to get back into it. The rest of the article will discuss how quickly context is lost, how long it takes to restore it, and what effect it has on the quality of your work.

How quickly does working memory degrade?

In 1959, an article titled, “Short-Term Retention of Individual Verbal Items” by L. Peterson and M. Peterson appeared in the Journal of Experimental Psychology [Source: http://www-test.unifr.ch/psycho/site/assets/files/Allg/ExU/Peterson_1959.pdf]. It showed that on average, after only 3 seconds, about half of our working memory is lost. The following graph plots the amount of working memory preserved after every subsequent 3 seconds:

After 15 seconds, less than 10% of the original memory is preserved. While these results may not be directly applicable to the programming context, it is clear that memory degradation occurs after seconds, not minutes. Translated, it means that short distractions cause dramatic losses in working memory.

How long it takes to restore context after an interruption?

Although there’s not a direct answer to that question, going through the relevant literature gives us some clues:

[…] the recovery time after a phone call is at least 15 minutes. [...] If more than 10 interrupts occur during a day, the time between the interrupts becomes too short to accomplish product development work.
Rini van Solingen et al, Interrupts: Just a Minute Never Is

To take a call you need to completely switch away from your working environment and focus on the conversation. Other interrupts are less disruptive than that:

Recovering from an email interrupt, and returning to work at the same work rate as before the interrupt — 64 seconds.
Thomas Jackson et al, Case Study: Evaluating the Effect of Email Interruptions within the Workplace

Instant message — 11 to 25 seconds.
Thomas Jackson, Instant Messaging Implications in the Transition from a Private Consumer Activity to a Communication Tool for Business

FYI – These quotes are not based on software developers, but rather more generic office workers. Take that as you’d like. Since context recovery is a process, it takes some time to get back to maximum speed after an interrupt:

The trouble is, getting into “the zone” is not easy. When you try to measure it, it looks like it takes an average of 15 minutes to start working at maximum productivity. [...] The other trouble is that it’s so easy to get knocked out of the zone. Noise, phone calls, going out for lunch, having to drive 5 minutes to Starbucks for coffee, and interruptions by coworkers [...] all knock you out of the zone.
Joel Spolsky, Where do These People Get Their (Unoriginal) Ideas?

So what about development Turnaround — should that be considered an interrupt and how much does it add to the cost?

From experience, any pause will cause the working memory to start fading, and longer pauses will cause developers to multi-task (even if the other task is reading Slashdot). This will mean that the context surrounding a particular task is at least partially lost and needs to be restored. A longer pause means more memory degradation, increased likelihood of a task switch, and the assumption that recovery time is also longer. Just to illustrate, let’s assume that it takes 50% of the length of the pause to recover the context after getting back to work. In that case, the total cost of turnaround for a java developer dealing with average build and redeploy delays looks something like:

  • 16.5 (mins per hour spent on Build & Redeploy phases) + 50% = 24.75 minutes per hour of development or 41.25% of coding time
  • 1200 (coding hours per year) * 41.25% = 495 hours per year spent on Turnaround (divide that by 40 hours per week to get 12.375 full-time work-weeks a year spent on turnaround)
  • Assuming a $20/h average salary this adds up to 495 * 20 = $9900 per developer per year

These numbers make a lot of assumptions. I’m not convinced that the average hourly wage of someone reading this blog is $20. I’m also not convinced that these numbers make an air-tight argument — but the point here is: the social cost of Turnaround is more than just the time spent on building, redeploying, & restarting.

Finally, I’m not convinced that developers keep all the code they wrote on a day full of distractions – I get the feeling that long turnaround times, distractions, and interruptions have a negative effect on code quality, and on the mental abilities of other developers. Though we couldn’t find data measuring this specifically, there is some indication that this impact is also not trivial, and I’d like to finish with it:

In a series of tests carried out by Dr Glenn Wilson, Reader in Personality at the Institute of Psychiatry, University of London, an average worker’s functioning IQ falls ten points when distracted by ringing telephones and incoming emails. This drop in IQ is more than double the four point drop seen following studies on the impact of smoking marijuana. Similarly, research on sleep deprivation suggests that an IQ drop of ten points is equal to missing an entire night of sleep. This IQ drop was even more significant in the men who took part in the tests.
Dr Glenn Wilson

Many programmers appear to be continually frustrated in attempts to work. They are plagued by noise and interruption, and pessimistic that the situation will ever be improved. The data recorded about actual interruptions supports the view that the so-called “work-day” is made up largely of frustration time.
T. DeMarco and T. Lister, Programmer performance and the effects of the workplace,

Conclusions

It’s been a long trip from the beginning of the series to this point. We can only hope that we answered some of your questions and maybe posed some new questions to answer. Probably the most important point that we were trying to bring to your attention is that reducing Java turnaround is a complex and expensive problem, which deserves a lot more attention than it’s getting at the moment

What are your thoughts on all this?

Resources

Other Articles in the Reloading Java Classes Series

One common comment we hear when talking about JRebel is that class updates should be implemented in the standard JVM (see feature comparison and behind-the-scenes notes to find out more about JRebel and HotSwap). However even if Oracle or IBM would announce tomorrow that they implemented the support for full schema change HotSwap in the next version of the JVM, JRebel would still be a worthwhile investment. Why?

1. Adding new classes

HotSwap protocol works by specifying the class name and the updated bytecode. It works for existing classes because there’s a relatively unique correspondence between the class name and its content. HotSwap ignores the fact that each class is loaded in a specific class loader. However to add a new class you need to choose that class loader, which HotSwap doesn’t support.

In exploded deployment (where WARs, EARs and JARs are deployed unpacked as directories) new classes can be loaded directly from the file system. But in packaged deployment (WARs, EARs and JARs deployed as archives) adding new classes is a challenge. Even adding the new class to the archive will not do the trick, as the archives are commonly unpacked when deployed and updating the archive either causes redeployment or no change whatsoever.

To solve this problem in a standard & compatible way you’d need:

  • A new standard API for Java EE that would allow you to find the corresponding class loader for a specified application. This would need to be implemented by the application server.
  • Extensions to the HotSwap protocol to allow sending new classes for a specified class loader, OR a different API/protocol to allow remote interaction with the IDE. This would need to be implemented in the JVM.
  • each IDE to be aware of what application the new classes belong to. This would need to be supported by the IDE.

JRebel solves this by

  • Extending the application server class loaders to search for classes from JRebel sources.
  • Using the rebel.xml configuration file to match each specific class loader to the classes in the IDE.

2. Resources

The HotSwap protocol doesn’t make any mention of the resources packaged along with classes. Java applications include quite a few of these (XMLs, property files, graphic files, etc). If you use packaged deployment these resources will not be updated until you make a full build and redeploy.

To solve this problem in a standard & compatible way you’d need:

  • A new standard API for Java EE that would allow you to find the corresponding class loader for a specified application. This would need to be implemented by the application server.
  • Extensions to the ClassLoader API to allow adding external sources for finding resources. This would need to be implemented by the application server.
  • Extensions to the HotSwap protocol to allow sending resources for a specified class loader or a different API/protocol to allow remote interaction with the IDE. This would need to be implemented in the JVM. A big problem with this approach is that resource names are often not unique and several distinct resources with the same name in the same application are quite common.
  • The IDE to be aware of which application the resources belong to. This would need to be supported by the IDE. Possibly you’d need to know even more about resources to solve the problem described in the previous point.

JRebel solves this by

  • Extending the application server class loaders to search for resources from JRebel sources.
  • Using the rebel.xml configuration file to match specific class loader to the resources in the IDE. JRebel solves the problem with multiple resources by giving the user control via rebel.xml to affect the order in which those resources are returned to the application.

3. Web resources

Besides the class loader resources, that are looked up via the ClassLoader API, every web application has a wealth of web resources like HTML, JSP, CSS, JS, images and so on. Unlike the class loader resources these are available in two ways:

  1. Served to the end user via the HTTP protocol.
  2. Read by the application using the ServletContext API.

If you use packaged deployment, then to update these resources you would need to do a full build and redeploy. HotSwap isn’t aware of these resources (and probably shouldn’t be), since ClassLoaders do not participate in any way in finding these resources.

To solve this problem in a standard & compatible way you’d need:

  • A new standard API for Java EE that would allow you to find the corresponding ServletContext or similar API for a specified application. This would need to be implemented by the application server.
  • A remote API for updating/injecting web resources into a specified ServletContext. These resources must also be served via HTTP when requested. This would need to be implemented by the application server. Luckily, unlike the class loader resources, web resources are uniquely identified by their name.
  • The IDE to be aware of which application the web resources belong to. This would need to be supported by the IDE.

JRebel solves this by

  • Extending the application server ServletContext implementation and HTTP server implementations to search for web resources from JRebel sources.
  • Using the rebel.xml configuration file to match a specific web application to the web resources in the IDE.

4. Caches

So let’s say the powers that be in the Java world have teamed up and implemented everything we described so far. You start your application, add a new method to the class, open your browser and stare at a juicy MethodNotFoundError. As it turns out, Java servers and frameworks tend to aggressively cache:

  • Class structure information. This means that the servers/frameworks won’t be aware of the new methods and will fail. A good example is JSP EL and Scriptlets, which will fail in most implementations when trying to access a new method.
  • Resources. Here we have both positive caches (the updated content is ignored) and negative caches (the new resource isn’t visible). Almost every server and some frameworks will include both of these caches.
  • Configuration. Many resources (and class annotations) are only scanned once, and all changes are ignored afterwards. E.g. Spring XML configuration or Annotations.

This means that even after both JVM and the application server APIs are updated to support application updates, you still need to re-engineer a lot of Java code to accept the fact that classes and resources can change.

JRebel solves this by

  • Purging the class structure information using listeners called when a class is updated and a lot of bytecode instrumentation to change the current framework implementations.
  • Integrating with servers and frameworks to intelligently disable or alter the positive and negative caches. JRebel introduces its own update-aware cache to speed up resource lookup and delivery.
  • Deeply integrating with frameworks to allow updates to the configuration. E.g. for Spring, JRebel causes the XMLs to be reread and the classpath to be rescanned.

5. Managed Components (EJBs, Spring beans,…)

Finally, when all is said and done, we still have the framework- or server-managed components like EJBs. These components often have:

  • Some kind of state associated with an instance or an instance pool.
  • Layers of proxies implementing aspects of functionality.
  • Dependency injection.

These features mean that updating the class schema is nowhere near enough. When a class is updated:

  • State may need to be updated to correspond to changes in the configuration. E.g. another method should now be executed inside a transaction.
  • Proxies may need to be reconstructed or updated to apply to the added methods. Otherwise you might be looking at the MethodNotFoundError again.
  • New dependencies must be injected. Otherwise NullPointerExceptions will abound.

Implementing this in current servers and frameworks will mean a substantial re-engineering across the codebase. JRebel solves this by re-implementing some server/framework features to allow for such updates to take place.

Conclusions

Although it could be possible to implement all of JRebel’s features in the Java ecosystem, it would take much more than just an update to the JVM. You’d need to re-engineer standards, introduce new APIs, implement them across app servers and then re-engineer much of the existing server/framework code base to take the possibility of updates into account. JRebel not only allows updates to class schema to take place, but also solves all those problems so that you can just update your code and see the change immediately. On average, that saves 2.5 minutes per redeploy — 5 times per hour of coding, and as Craig Pardey noticed, a whole bunch of context switching as well.

« Newer Entries | Older Entries »

Join the Rebellion Facebook Twitter RSS feed