有一个解决方案可以使用 java 版本低于 1.6.0_26 的序列化 ImageIcon 类,并通过替换 serialVersionUID 字段使用 1.6.0_26 的 java 版本反序列化:
/**
* Replace serialVersionUID of class {@link javax.swing.ImageIcon}.
*
* Hack due to serialVersionUID change but data has not changed since java 1.6.0_26. Cf. http://stackoverflow.com/questions/18782275/facing-issue-with-serialversionuid
*
* @return the bytes array converted; or null if conversion failed, or no conversion has been done.
*/
private byte[] convertSerializedData(final byte[] viewsData) {
try (final ByteSequence byteSequence = new ByteSequence(viewsData)) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final DataOutputStream dataOutputStream = new DataOutputStream(baos);
while (byteSequence.available() > 0) {
final byte readByte = byteSequence.readByte();
dataOutputStream.writeByte(readByte);
if (readByte == ObjectStreamConstants.TC_CLASSDESC) {
byteSequence.mark(byteSequence.getIndex());
boolean discard = false;
try {
final String className = byteSequence.readUTF();
long serialVersionUID = byteSequence.readLong();
if ("javax.swing.ImageIcon".equals(className) && serialVersionUID == 532615968316031794L) {
// Replace serialVersionUID of class javax.swing.ImageIcon
serialVersionUID = -962022720109015502L;
dataOutputStream.writeUTF(className);
dataOutputStream.writeLong(serialVersionUID);
} else
discard = true;
} catch (final Exception e) {
// Failed to read class name, discard this read
discard = true;
}
if (discard)
byteSequence.reset();
}
}
dataOutputStream.flush();
return baos.toByteArray();
} catch (final Exception e) {
// Conversion failed
}
return null;
}
以下是使用此方法的示例,该方法仅在引发异常时调用:
public void restoreViews(final byte[] viewsData) {
try {
if (viewsData != null) {
final ByteArrayInputStream bais = new ByteArrayInputStream(viewsData);
final ObjectInputStream objectInputStream = new ObjectInputStream(bais);
readInputStream(objectInputStream);
objectInputStream.close();
}
} catch (final Exception e) {
try {
final byte[] viewsDataConverted = convertSerializedData(viewsData);
if (viewsDataConverted != null) {
final ByteArrayInputStream bais = new ByteArrayInputStream(viewsDataConverted);
final ObjectInputStream objectInputStream = new ObjectInputStream(bais);
readInputStream(objectInputStream);
objectInputStream.close();
}
} catch (final Exception e2) {
InfonodeViewManager.LOGGER.error("Unable to restore views", e);
}
}
}