Ich erstellte Client und Server und fügte dann auf der Clientseite eine Klasse hinzu, um sie zu serialisieren. Dann ging ich einfach in den Ordner des Clients auf meiner Festplatte und kopierte ihn in den entsprechenden Speicherort des Servers, jeweils classname.class
und classname.Java
.
Bei meinem eigenen Laptop hat es gut funktioniert. Als ich jedoch meine Arbeit auf einem anderen System fortsetzen wollte, beim Öffnen der Projektordner und nachdem der Client versucht, eine Verbindung zum Server herzustellen, wird der folgende Fehler angezeigt:
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)
Was ist los? Liegt es daran, dass ich das Programm mit einer älteren Version der IDE ausgeführt habe?
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;
}
Wenn eine Klasse einen private static final long serialVersionUID
nicht explizit im Code definiert, wird sie automatisch generiert, und es gibt keine Garantie, dass verschiedene Maschinen dieselbe ID generieren. Es sieht so aus, als sei genau das passiert, was passiert ist ..__ Auch wenn die Klassen in irgendeiner Weise unterschiedlich sind (unter Verwendung verschiedener Versionen der Klasse), werden auch die automatisch generierten serialVersionUID
s unterschiedlich sein.
Aus der Serializable
-Schnittstelle docs :
Wenn eine serialisierbare Klasse einen
serialVersionUID
nicht explizit deklariert, berechnet die Serialisierungslaufzeit einenserialVersionUID
-Standardwert für diese Klasse basierend auf verschiedenen Aspekten der Klasse, wie in der Java (TM) Object Serialization Specification beschrieben. Es ist jedoch dringend empfohlen, dass alle serialisierbaren Klassen explizitserialVersionUID
-Werte deklarieren, da die StandardberechnungserialVersionUID
sehr empfindlich auf Klassendetails reagiert, die je nach Implementierung des Compilers variieren können und daher während der Deserialisierung zu unerwartetenInvalidClassExceptions
-Werten führen kann. Um einen konsistentenserialVersionUID
-Wert über verschiedene Java-Compiler-Implementierungen hinweg zu gewährleisten, muss eine serialisierbare Klasse einen explizitenserialVersionUID
-Wert deklarieren. Es wird außerdem dringend empfohlen, dass expliziteserialVersionUID
-Deklarationen soweit möglich den Modifiziererprivate
verwenden, da solche Deklarationen nur für die unmittelbar deklarierenden Klasse gelten -serialVersionUID
-Felder sind als geerbte Mitglieder nicht nützlich. Array-Klassen können keine explizitenserialVersionUID
-Werte deklarieren. Daher haben sie immer den berechneten Standardwert. Die Anforderung für den Abgleich vonserialVersionUID
-Werten für Array-Klassen wird jedoch weggelassen.
Sie sollten in der Klassendefinition ein serialVersionUID
definieren, z. B .:
class MyClass implements Serializable {
private static final long serialVersionUID = 6529685098267757690L;
...
Eine Sache, die hätte passieren können:
Zum Zeitpunkt der Kompilierung für die Version X generiert die JVM daher eine erste Serien-ID (für Version X) und dies auch mit der anderen Version Y (einer anderen Serien-ID).
Wenn Ihr Programm versucht, die Daten zu deserialisieren, ist dies nicht möglich, da die beiden Klassen nicht dieselbe Serien-ID haben und Ihr Programm keine Garantie dafür gibt, dass die beiden serialisierten Objekte demselben Klassenformat entsprechen.
Angenommen, Sie haben Ihren Konstruktor zwischenzeitlich geändert und dies sollte für Sie sinnvoll sein.
Die Ausnahmemeldung besagt eindeutig, dass sich die Klassenversionen, die auch die Metadaten der Klasse enthalten würden, im Laufe der Zeit geändert haben. Mit anderen Worten, die Klassenstruktur während der Serialisierung ist während der Deserialisierung nicht gleich. Dies ist, was höchstwahrscheinlich "los" ist.
Ich glaube, dass dies der Fall ist, weil Sie die verschiedenen Versionen derselben Klasse auf Client und Server verwenden
Wenn Sie oc4j zum Bereitstellen des Ohrs verwenden.
Stellen Sie sicher, dass Sie im Projekt den richtigen Pfad für deploy.home = festgelegt haben
Sie können deploy.home in der Datei common.properties finden
Das oc4j muss die neu erstellte Klasse im Ohr neu laden, damit die Serverklasse und die Clientklasse dieselbe serialVersionUID haben
Serialisierung in Java ist nicht als Langzeitpersistenz oder Transportformat gedacht - dafür ist es zu zerbrechlich. Mit dem geringsten Unterschied in Klassenbytecode und JVM sind Ihre Daten nicht mehr lesbar. Verwenden Sie XML- oder JSON-Datenbindung für Ihre Aufgabe ( XStream ist schnell und einfach zu verwenden, und es gibt eine Vielzahl von Alternativen)