I am facing some issues while serializing objects (I am using JBoss Drools, and want to store an ArrayList of KnowledgePackage).
When I serialize the list, store the result in a file, and deserialize it, no problem occurs, so it works fine.
But when I serialize the list, store the result in a byte stream, then save it in a JarFile, i cannot then deserialize the result, because of this error :
IOException during package import : java.util.ArrayList; local class incompatible: stream classdesc serialVersionUID = 8664875232659988799, local class serialVersionUID = 8683452581122892189
So I think the issue is when I am saving the serialized object into a Jarfile entry. I think I am doing this right, because other files saved the same way in the Jarfile can correctly be read.
And after using ‘cmp’ and ‘hexdump’, I have spotted that saving it it an jar causes a variation of one octet if the uuid, else the content is the same.
I am really disappointed and can not state where the problem may be.
What can modify the SerialVersionUID between two classes ? other than another vm version ?
adding source code :
exportToJar -> writeRulesPackageEntry -> writeEntry
/**
* Writes content provided from a reader into a file contained in a jar.
*
* @param output the output stream to write on
* @param entryName the name of the file that will contain reader data
* @param contentReader
*
* @return the zip entry that has been created into the jar
*/
ZipEntry writeEntry(JarOutputStream output, String entryName, ByteArrayInputStream input) {
if (output == null || entryName == null || entryName.trim().length() == 0 || input == null) {
throw new NullPointerException("Null argument passed");
}
ZipEntry entry = new ZipEntry(entryName);
byte[] buffer = new byte[BUFFER_LENGTH];
try {
output.putNextEntry(entry);
int nRead;
while ((nRead = input.read(buffer, 0, BUFFER_LENGTH)) > 0) {
output.write(buffer, 0, nRead);
}
output.closeEntry();
} catch (IOException e) {
e.printStackTrace();
}
return entry;
}
/**
* Export rules files to a serialized object (ArrayList<KnowledgePackage>) into
* an output stream, then write the output content as an entry of a jar.
*
* @param os the output jar to write in
*/
void writeRulesPackageEntry(JarOutputStream os) {
// serialize objects and write them to the output stream
ByteArrayOutputStream output = new ByteArrayOutputStream();
RulesPackaging rulesPackaging = new RulesPackaging();
rulesPackaging.exportResources(this.rules, output);
// create a new input stream to read written objects from
ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
this.writeEntry(os, Product.ENTRY_RULES_PACKAGE, input);
}
/**
* Creates a JarFile containing resources.
*
* @param filename the exported jar filename
* @return the jar as an object, null if an error occured
*/
public JarFile exportToJar(String filename) {
FileOutputStream fOs;
JarOutputStream jOs;
JarFile jar = null;
try {
fOs = new FileOutputStream(filename);
jOs = new JarOutputStream(fOs);
this.writeRulesPackageEntry(jOs);
jOs.close();
// construct a jar from the output jar
jar = new JarFile(new File(filename));
} catch (IOException e) {
e.printStackTrace();
}
return jar;
}
The
serialVersionUIDdoesn’t change. It is astatic finalassigned at compilation time (based on a hash of the source code, I think) unless a value is assigned explicitly in the source code.There’s a bit more about it here http://mindprod.com/jgloss/serialization.html.
With the exception you are seeing the correct
serialVersionUIDfor java.util.ArrayList is 8683452581122892189L, which is assigned explicitly in the source code and has remained the same since the class was introduced in 1.2.As you’ve said the error is most likely occurring when byte stream to the JarFile – please post the code you’re using to do that.
Cont’d after the source code was posted
I suspect the problem lies in the use of the
java.io.InputStreamReader.From the JavaDoc:
As soon as I see character sets involved in non-text streams I always get suspicious because it’s possible for the stream to be modified during the decoding is a sequence of bytes doesn’t correspond to a character in the character set (seen those little square characters that occurs when encoding issues happen). I would try reading the bytes straight off the
java.io.ByteArrayInputStreamthat you are wrapping with thejava.io.InputStreamReaderinwriteRulesPackageEntry(JarOutputStream). The conversion to achar[]isn’t necessary.