ce qui pourrait modifier le serialVersionUID lors de la sérialisation et le stockage dans un fichier jar?

StackOverflow https://stackoverflow.com/questions/1092255

Question

Je suis confronté à des problèmes alors que les objets sérialisation (je suis en utilisant JBoss Drools, et que vous souhaitez stocker une liste de tableaux KnowledgePackage).

Quand je sérialiser la liste, stocker le résultat dans un fichier, et désérialiser, aucun problème se produit, il fonctionne très bien.

Mais quand je sérialiser la liste, stocker le résultat dans un flux d'octets, puis enregistrez-le dans un fichier Jar, je ne peux pas désérialiser le résultat, en raison de cette erreur:

IOException during package import : java.util.ArrayList; local class incompatible: stream classdesc serialVersionUID = 8664875232659988799, local class serialVersionUID = 8683452581122892189

Je pense donc que la question est quand je sauve l'objet sérialisé dans une entrée JarFile. Je pense que je fais ce droit, parce que d'autres fichiers enregistrés de la même manière dans le JarFile correctement peut être lu. Et après l'utilisation de « cmp » et « hexdump », je l'ai repéré que l'enregistrer en fait un pot provoque une variation d'un octet si l'UUID, sinon le contenu est le même.

Je suis vraiment déçu et ne peut pas état où le problème peut être.

Que peut modifier le serialVersionUID entre deux classes? autre qu'une autre version vm?


en ajoutant le code de source:  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;
}
Était-ce utile?

La solution

Le serialVersionUID ne change pas. Il est un static final affecté au moment de la compilation (basée sur un hachage du code source, je pense) à moins qu'une valeur est affectée explicitement dans le code source.

Il y a un peu plus à ce sujet ici http://mindprod.com/jgloss/serialization.html .

A l'exception que vous voyez le serialVersionUID correct pour java.util.ArrayList est 8683452581122892189L, qui est attribué explicitement dans le code source et est restée la même depuis la classe a été introduite en 1.2.

Comme vous l'avez dit l'erreur est plus probable qui se produit lorsque le flux d'octets du fichier Jar -. S'il vous plaît afficher le code que vous utilisez pour faire

après le code CONT'D source a été publié

Je suppose que le problème réside dans l'utilisation du java.io.InputStreamReader.

De la JavaDoc:

  

Un InputStreamReader est un pont à partir de   octet flux de flux de caractères: Il   lit les octets et les décode en   caractères en utilisant un jeu de caractères spécifié.   Le jeu de caractères qu'il utilise peut-être   spécifié par son nom ou peut être donné   explicitement ou par défaut de la plate-forme   charset peut être acceptée.

Dès que je vois des jeux de caractères impliqués dans non-texte, je les ruisseaux toujours se méfier car il est possible pour le flux à modifier lors du décodage est une séquence d'octets ne correspond pas à un personnage dans le jeu de caractères (voir ces petits caractères carrés qui se produit lorsque des problèmes se produisent codant). Je voudrais essayer de lire les octets d'emblée la java.io.ByteArrayInputStream que vous envelopper avec le java.io.InputStreamReader dans writeRulesPackageEntry(JarOutputStream). La conversion à un char[] n'est pas nécessaire.

Autres conseils

Comme Nick propose, la question est plus probable que vous ne traitez pas le flux sous forme d'octets (qui ne sont jamais modifiés), mais comme des caractères (qui peut être).

Cela dit, une autre ressource décent sur sérialisation est un chapitre dédié d'un livre que j'ai écrit il y a un million d'années (1997), « La maîtrise de JavaBeans ». Heureusement, le chapitre 11, sérialisation, est aussi pertinente aujourd'hui qu'elle l'était alors. Télécharger les fichiers PDF gratuits de http://ccd.uab.es/~srobles/manuals/JavaBeans

Est-il possible qu'une version antérieure a été publié en feuilleton dans le JarFile, et les tentatives de sérialisation ultérieures ne parviennent pas à le remplacer? Ensuite, vous seriez récupérer les données sérialisées d'une version antérieure de la classe, qui (à juste titre) jeter l'erreur « incompatible ».

La raison pour laquelle je demande, est que j'ai vu des messages d'erreur similaires en utilisant mon système de mise en cache de choix (EHCache) quand je l'ai mis à jour une classe sérialisée encore ai pas abandonné l'ancien cache persistant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top