Matthew Hall created BEANUTILS-450:
--------------------------------------

             Summary: BeanUtilsBean.getInstance() pseudo-singleton causes 
problems with Java 7 parallelized class loader
                 Key: BEANUTILS-450
                 URL: https://issues.apache.org/jira/browse/BEANUTILS-450
             Project: Commons BeanUtils
          Issue Type: Bug
          Components: Bean / Property Utils, ConvertUtils & Converters
    Affects Versions: 1.7.0
            Reporter: Matthew Hall
            Priority: Blocker


>From an email I sent to the BeanUtils users mailing list:

We recently tracked a bug in our software that started showing up with Java 7 
back to an incompatibility between BeanUtilsBean.getInstance() pseudo-singleton 
instance model, Java 7’s parallelized class loader, and the fact that we were 
registering Converters with ConvertUtils inside of a static class-level block. 
As far as I’m able to tell, this wasn’t a problem in previous versions of Java 
because the class loader was not parallelized, meaning that the class loader 
that handled the registration of our converters was the same class loader that 
was in use when ConvertUtilsBean.getInstance() was invoked. Now, with Java 7, 
it seems that there is no guarantee that the class loader that executes the 
static block containing the Converter registration is the same one in use when 
ConvertUtilsBean.getInstance() is invoked, meaning that our custom Converters 
are not necessarily available everywhere they used to be.

I’m writing to the list today to ask three things about this situation:

 1.  First off, is this the correct explanation for the reason that it seems 
we’re not guaranteed to have our custom Converters loaded in Java 7.
 2.  In order to ensure that a different class loader thread is not in use when 
the Converters are registered with ConvertUtils, we’ve moved this registration 
from a static class-level block into a user interface setup method that is 
executed before the Converters are used.
 3.  Given that Java 7 introduced parallelized class loading in the base 
ClassLoader and that BeanUtilsBean builds instances on a per-classloader basis, 
should this issue be raised to the BeanUtils developers?

Below you’ll find some pseudocode that illustrates our situation:

public class UtilitiesClass {
   ...
   static {
       ConvertUtils.register(new OurCustomColorConverter(), 
java.awt.Color.class);
   }
   ...
}

public class MainGUIClass {
   ...
   public static void main(String[] args) {
       MainGUIClass mainGui = new MainGUIClass();
       mainGui.setup();
       mainGui.show();
   }

   public void setup() {
       UIManager.setLookAndFeel(new LookAndFeelClass());
   }

   public void show() {
       ((OurLookAndFeelClass) UIManager.getLookAndFeel()).getColor();
   }
   ...
}

public class LookAndFeelClass extends LookAndFeel {
   ...
   public java.awt.Color getColor(String colorString) {
       return (java.awt.Color) ConvertUtils.convert("someValidColorString", 
java.awt.Color.class);
   }
   ...
}

In the above example, the cast of the results of ConvertUtils.convert to Color 
in LookAndFeelClass.getColor(String) sometimes results in a runtime exception 
with the message “java.lang.String cannot be cast to java.awt.Color.”. This 
appears to be due to the fact that ConvertUtils.convert() fails over to the 
built-in String.class Converter if it cannot find a Converter for the specified 
class. In production environments, it was completely unpredictable as to when 
this would happen and what would make the problem go away.

The fix we implemented was to move the registration of 
OurCustomColorConverter() from the static block inside of UtilitiesClass to the 
first line of MainGUIClass.setup(), before the LookAndFeel is loaded. Will this 
fix be sufficient, or does it still suffer from the thread issue, if that is 
indeed the root cause of the problem?



--
This message was sent by Atlassian JIRA
(v6.1#6144)

Reply via email to