【问题标题】:ArrayIndexOutOfBoundException on XMLDecoder.readObject()XMLDecoder.readObject() 上的 ArrayIndexOutOfBoundException
【发布时间】:2018-07-11 05:23:19
【问题描述】:

在我的程序中有一些场景,我将从属性文件中获取空对象,如下所示

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

在下面的代码中读取空对象

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

            Object object = decoder.readObject();

            decoder.close();

            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(propDef.getKey());
            s.append("] XML contents [");
            s.append(data.toString());
            s.append("]");
            throw new RuntimeException(s.toString(), e);
        }
    }

在尝试读取上面代码中的空对象时,decoder.readObject() 我面临以下错误

java.lang.RuntimeException: XmlNativeTranslator.translateFromStorage: 无法翻译属性定义键 [FORMS_KEY] XML 内容 [ ] 原因: java.lang.ArrayIndexOutOfBoundsException: 0

需要一种方法来处理这种情况

【问题讨论】:

    标签: java arrays java-8 xml-serialization indexoutofboundsexception


    【解决方案1】:

    java.util.Map 是一个接口,你不应该以序列化的形式遇到它,因为不可能有接口的直接实例。

    空地图的有效表达式是,例如

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

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

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

    XMLDecoder 具有在异常情况下继续的可疑特性,导致ArrayIndexOutOfBoundsException 作为后续错误。

    你可以强制它抛出实际的异常:

    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;
    

    请注意,使用StringReader 无需处理任何编码错误。我还删除了close() 步骤,因为StringReader 没有附加资源,而XMLDecoder.close() 在我们使用try-with-resource 的例外情况下会导致更多的后续错误。

    手动使用StringBuffer 对这里的字符串连接没有任何改进;在 Java 5 之前,编译器会生成几乎相同的代码,因为 Java 5 它使用 StringBuilder 生成类似的代码,效率更高,更不用说 Java 9 和更新的更好了。

    使用您的示例输入运行此代码会产生

    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">
    </object>
    </java>]
        at ListFiltersToGetMatchingRecords.lambda$main$0(ListFiltersToGetMatchingRecords.java:35)
        at com.sun.beans.decoder.DocumentHandler.handleException(DocumentHandler.java:359)
        at com.sun.beans.decoder.NewElementHandler.getValueObject(NewElementHandler.java:126)
        at com.sun.beans.decoder.ElementHandler.endElement(ElementHandler.java:169)
        at com.sun.beans.decoder.DocumentHandler.endElement(DocumentHandler.java:318)
    … shortened …
        at com.sun.beans.decoder.DocumentHandler.parse(DocumentHandler.java:372)
        at java.beans.XMLDecoder$1.run(XMLDecoder.java:201)
        at java.beans.XMLDecoder$1.run(XMLDecoder.java:199)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.beans.XMLDecoder.parsingComplete(XMLDecoder.java:199)
        at java.beans.XMLDecoder.readObject(XMLDecoder.java:250)
        at ListFiltersToGetMatchingRecords.main(ListFiltersToGetMatchingRecords.java:38)
    Caused by: java.lang.InstantiationException: java.util.Map
        at java.lang.Class.newInstance(Class.java:427)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    … shortened …
        at java.beans.Statement.invoke(Statement.java:182)
        at java.beans.Expression.getValue(Expression.java:155)
        at com.sun.beans.decoder.ObjectElementHandler.getValueObject(ObjectElementHandler.java:166)
        at com.sun.beans.decoder.NewElementHandler.getValueObject(NewElementHandler.java:123)
        ... 24 more
    Caused by: java.lang.NoSuchMethodException: java.util.Map.<init>()
        at java.lang.Class.getConstructor0(Class.java:3082)
        at java.lang.Class.newInstance(Class.java:412)
        ... 42 more
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-27
      • 1970-01-01
      • 2017-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多