我最近升级到Java 7,我注意到XML序列化有一个奇怪的问题。基本上,我有一个测试实用程序类,它使用 XML 编码器执行对象到 XML 的转换。
请参阅下面的示例代码:
public static String toXML(Object obj) {
String retval = null;
if(obj != null) {
XMLEncoder encoder = null;
ByteArrayOutputStream bos;
try {
bos = new ByteArrayOutputStream();
encoder = new XMLEncoder(bos);
encoder.writeObject(obj);
encoder.close();
byte[] bytes = bos.toByteArray();
if(bytes != null) {
retval = new String(bytes);
}
} catch(Exception e) {
e.printStackTrace();
} finally {
if(encoder != null) {
encoder.close();
}
}
}
return retval;
}
这在 Java 1.6 中运行良好,但是自从我升级到 Java 1.7 以来,我注意到 XML 编码器操作在日志中抛出了一个 IOException:
java.io.IOException: Stream closed
at sun.nio.cs.StreamEncoder.ensureOpen(StreamEncoder.java:45)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:140)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at java.beans.XMLEncoder.flush(XMLEncoder.java:497)
at java.beans.XMLEncoder.close(XMLEncoder.java:530)
at com.mytestcode.server.common.util.TestSerializer.toXML(TestSerializer.java:87)
我查看了XMLEncoder代码,发现StreamEncoder.ensureOpen对isOpen进行了检查,这似乎是错误的。
这个问题看起来很相似,尽管它没有使用 Java 1.7 XML 编码器。我还没有看到 XML 编码器或这种方法的一般问题,我可以在代码中修复什么还是看起来更下游?我错过了什么?
我终于能够弄清楚这一点。麻烦是因为Java 6到7的升级。
Java 6和 7 之间的区别,XMLEncoder 表明,在 Java 6 中,XML 编码器直接在构造函数中传递的 ByteArrayOutputStream 上工作,而在Java 7中,XMLEncoder将StreamEncoder包装在构造函数中传递的ByteArrayOutputStream周围。
(第289行)
http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/beans/XMLEncoder.java/?v=diff&id2=6-b14
虽然调用 ByteArrayOutputStream.close()(参见 Javadoc)绝对不执行任何操作,但如果 StreamEncoder.close()(参见 Javadoc)已经关闭,则会抛出可恢复的 IOException。
此异常将选取默认的 ExceptionListener 并记录在日志中。