ArrayIndexOutOfBoundException on XMLDecoder.readObject()

There are scenarios in my program where i will be getting the empty object from the properties file as shown below

<?xml version="1.0" encoding="UTF-8"?> 
 <java version="1.4.1" class="java.beans.XMLDecoder"> 
 <object class="java.util.Map">

On reading the empty object in below code

public Object translateObj(
        String data,
        PropertyDefinition propDef) {
        try {
            XMLDecoder decoder =
                new XMLDecoder(new BufferedInputStream(new ByteArrayInputStream(data.getBytes("UTF-8"))));

            Object object = decoder.readObject();


            return object;
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("XmlNativeTranslator.translateFromStorage: " +
                " Unable to UTF-8 encode inputData " + data.toString());
        } catch (ArrayIndexOutOfBoundsException e) {
            StringBuffer s = new StringBuffer();
            s.append("Failed to translate property definition key [");
            s.append("] XML contents [");
            throw new RuntimeException(s.toString(), e);

On trying to read the empty object in the above code in line decoder.readObject() i am facing the below error

java.lang.RuntimeException: XmlNativeTranslator.translateFromStorage: Failed to translate property definition key [FORMS_KEY] XML contents [ ] Caused by: java.lang.ArrayIndexOutOfBoundsException: 0

Need a way to handle this scenario

1 answer

  • answered 2018-07-11 12:29 Holger

    java.util.Map is an interface and you should never encounter it in a serialized form, as it is impossible to have direct instances of an interface.

    Valid expressions of empty maps would be, e.g.

    <object class="java.util.HashMap"/>


    <object class="java.util.Collections" method="emptyMap"/>


    <object class="java.util.Properties"/>

    The XMLDecoder has the questionable feature of proceeding in the exceptional case, which causes the ArrayIndexOutOfBoundsException as follow-up error.

    You can force it to throw the actual exception instead:

    XMLDecoder dec = new XMLDecoder(new InputSource(new StringReader(data)));
    dec.setExceptionListener(ex -> {
        throw ex instanceof RuntimeException? (RuntimeException)ex:
            new RuntimeException("Failed to translate property definition key"+
                " ["+propDef.getKey()+"] XML contents ["+data+"]", ex);
    Object object = dec.readObject();
    return object;

    Note that by using a StringReader there are no encoding errors to handle. I also removed the close() step as a StringReader has no attached resources and XMLDecoder.close() causes even more follow-up errors in the exceptional case when we use try-with-resource.

    Using a StringBuffer manually is no improvement over string concatenation here; before Java 5 ,the compiler would generate almost identical code, since Java 5 it generates similar code using StringBuilder which is even more efficient, not to speak of Java 9 and newer which are even better.

    Running this code with your sample input produces

    Exception in thread "main" java.lang.RuntimeException: Failed to translate property definition key [] XML contents [<?xml version="1.0" encoding="UTF-8"?> 
     <java version="1.4.1" class="java.beans.XMLDecoder"> 
     <object class="java.util.Map">
        at ListFiltersToGetMatchingRecords.lambda$main$0(
        at com.sun.beans.decoder.DocumentHandler.handleException(
        at com.sun.beans.decoder.NewElementHandler.getValueObject(
        at com.sun.beans.decoder.ElementHandler.endElement(
        at com.sun.beans.decoder.DocumentHandler.endElement(
    … shortened …
        at com.sun.beans.decoder.DocumentHandler.parse(
        at java.beans.XMLDecoder$
        at java.beans.XMLDecoder$
        at Method)
        at java.beans.XMLDecoder.parsingComplete(
        at java.beans.XMLDecoder.readObject(
        at ListFiltersToGetMatchingRecords.main(
    Caused by: java.lang.InstantiationException: java.util.Map
        at java.lang.Class.newInstance(
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    … shortened …
        at java.beans.Statement.invoke(
        at java.beans.Expression.getValue(
        at com.sun.beans.decoder.ObjectElementHandler.getValueObject(
        at com.sun.beans.decoder.NewElementHandler.getValueObject(
        ... 24 more
    Caused by: java.lang.NoSuchMethodException: java.util.Map.<init>()
        at java.lang.Class.getConstructor0(
        at java.lang.Class.newInstance(
        ... 42 more