Really a nasty bug

It’s a long time, I didn’t write a post in my blog. I just had a really heavy workload period.

Last week, I spent my whole sunday chasing a really nasty bug related to the XmlEncoder running an JVM 1.5 AIX 64bits

The symptoms where the followings, after a certain amount of time, a XML dump done using the XmlEncoder was throwing StackOverflowException. What was really strange is that the dumped object was correctly dumped a few second before and that a new dump was throwing the exception.o After some investigations, I came to the conclusion that the problem was due the PersistentDelegate used for the class (aka java_lang_Class_PersistentDelegate). I tried to bypass this default PersistentDelegate of the java.lang.Class object but then I got InvalidClassChangeError.

Eventually, I decided to rewrite the XmlEncoder and I found the issue.

In the java_lang_Class_PersistenceDelegate, there is the following code:

protected Expression instantiate(Object oldInstance, Encoder out) {        Class c = (Class)oldInstance;        // As of 1.3 it is not possible to call Class.forName("int"),        // so we have to generate different code for primitive types.        // This is needed for arrays whose subtype may be primitive.        if (c.isPrimitive()) {            Field field = null;        try {        field = ReflectionUtils.typeToClass(c).getDeclaredField("TYPE");        } catch (NoSuchFieldException ex) {                System.err.println("Unknown primitive type: " + c);            }            return new Expression(oldInstance, field, "get", new Object[]{null});        }        else if (oldInstance == String.class) {            return new Expression(oldInstance, "", "getClass", new Object[]{});        }        else if (oldInstance == Class.class) {            return new Expression(oldInstance, String.class, "getClass", new Object[]{});        }        else {            return new Expression(oldInstance, Class.class, "forName", new Object[]{c.getName()});        }    }

The issue was due to the code:

else if (oldInstance == Class.class) {

Before calling instantiate, oldInstance.toString() was returning class org.acme.Foo. However, within the instantiate method oldInstance == Class.class was returning true which for me is totally wrong.

As a workaround, I rewrited a PersistentDelegate and replace the if statement by:

else if (((Class) oldInstance).getName().equals(Class.class.getName())) {

And now it’s working properly.

It was a Sunday, I would have prefer to spend outside.

Comments are closed.