java.io.InvalidClassException: classe locale incompatible:
j'ai créé le client et le serveur et j'ai ensuite ajouté une classe dans le côté client à des fins de sérialisation, puis je suis simplement allé dans le dossier du client dans mon disque dur et j'ai copié le coller à l'emplacement correspondant au serveur, tous les deux classname.class
et classname.java
respectivement.
cela a bien fonctionné dans mon propre ordinateur portable mais quand j'ai voulu continuer mon travail sur un autre système, quand j'ai ouvert les dossiers de projets et après que le client a essayé de se connecter au serveur, l'erreur suivante s'affiche:
Exception in thread "main" java.io.InvalidClassException: projectname.clasname; local class incompatible: stream classdesc serialVersionUID = -6009442170907349114, local class serialVersionUID = 6529685098267757690
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:562)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
Ce qui se passe? Est-ce parce que j'ai lancé le programme avec une version plus ancienne de L'IDE?
EDIT
import java.io.Serializable;
import java.net.URL;
public class KeyAdr implements Serializable {
private static final long serialVersionUID = 6529685098267757690L;
public URL adr;
public String key;
}
5 réponses
Si une classe ne définit pas explicitement un private static final long serialVersionUID
dans le code, il sera autogénéré, et il n'y a aucune garantie que différentes machines généreront le même id; il semble que c'est exactement ce qui s'est passé.
En outre, si les classes sont différentes de quelque manière que ce soit (en utilisant différentes versions de la classe) l'autogénérisé serialVersionUID
s sera également différent.
Serializable
l'interface est docs:
Si une classe sérialisable ne pas déclarer explicitement un
serialVersionUID
, alors l'exécution de la sérialisation calculera unvaleur pour cette classe basée sur divers aspects de la classe, comme décrit dans la spécification de sérialisation D'objet Java(TM). Cependant, il est fortement recommandé que toutes les classes sérialisables déclarent explicitement serialVersionUID
valeurs, puisque la valeur par défaut estserialVersionUID
le calcul est très sensible aux détails de la classe qui peuvent varier en fonction des implémentations du compilateur, et peut donc entraîner inattenduInvalidClassExceptions
pendant la désérialisation. Par conséquent, pour garantir une cohérenceserialVersionUID
valeur à travers différentes implémentations de compilateurs java, une classe serialisable doit déclarer un < explicite!--2--> valeur. Il est également fortement conseillé expliciteserialVersionUID
les déclarations utilisent leprivate
modificateur dans la mesure du possible, puisque ces déclarations ne s'appliquent qu'à la classe déclarant immédiatement--serialVersionUID
les champs ne sont pas utiles comme membres hérités. Les classes Array ne peuvent pas déclarer unserialVersionUID
, de sorte qu'ils toujours la valeur par défaut valeur calculée, mais l'exigence d'appariementserialVersionUID
les valeurs sont supprimées pour les classes de tableaux.
Vous devez définir un serialVersionUID
dans la définition de la classe, par exemple:
class MyClass implements Serializable {
private static final long serialVersionUID = 6529685098267757690L;
...
Une chose qui puisse arriver:
- 1: vous créez vos données sérialisées avec une bibliothèque donnée A (version X)
- 2: vous essayez alors de lire ces données avec la même bibliothèque A (mais la version Y)
ainsi, au moment de la compilation pour la version X, la JVM générera un premier numéro de série (pour la version X) et fera de même avec l'autre version Y (un autre numéro de série).
quand votre programme essaie de désérialiser les données, il ne peut pas parce que les deux classes n'ont pas le même identifiant de série et que votre programme n'a aucune garantie que les deux objets sérialisés correspondent au même format de classe.
en supposant que vous avez changé votre constructeur dans l'intervalle et cela devrait avoir du sens pour vous.
je crois que cela se produit parce que vous utilisez les différentes versions de la même classe sur le client et le serveur. Il peut s'agir de différents champs de données ou méthodes
le message d'exception indique clairement que les versions de classe, qui incluraient également les métadonnées de classe, ont changé au fil du temps. En d'autres termes, la structure de classe pendant la sérialisation n'est pas la même pendant la désérialisation. C'est ce qui est le plus probablement "en cours".
la sérialisation en java n'est pas censée être une persistance à long terme ou un format de transport - elle est trop fragile pour cela. Avec la moindre différence entre class bytecode et JVM, vos données ne sont plus lisibles. Utilisez XML ou JSON data-binding pour votre tâche ( XStream est rapide et facile à utiliser, et il ya une tonne d'alternatives)