Eclipse gibt Warnungen aus, wenn a serialVersionUID
fehlt.
Die serialisierbare Klasse Foo deklariert kein statisches endgültiges serialVersionUID-Feld vom Typ long
Was ist serialVersionUID
und warum ist es wichtig? Bitte zeigen Sie ein Beispiel, bei dem das Fehlen serialVersionUID
ein Problem verursacht.
java
serialization
serialversionuid
ashokgelal
quelle
quelle
Antworten:
Die Dokumente für
java.io.Serializable
sind wahrscheinlich eine so gute Erklärung, wie Sie bekommen werden:quelle
Wenn Sie nur serialisieren, weil Sie für die Implementierung serialisieren müssen (wen interessiert es, wenn Sie beispielsweise für ein
HTTPSession
... ob es gespeichert ist oder nicht, interessieren Sie sich wahrscheinlich nicht fürde-serializing
ein Formularobjekt), können Sie dies ignoriere das.Wenn Sie tatsächlich die Serialisierung verwenden, ist dies nur wichtig, wenn Sie Objekte direkt mithilfe der Serialisierung speichern und abrufen möchten. Das
serialVersionUID
stellt Ihre Klassenversion dar, und Sie sollten es erhöhen, wenn die aktuelle Version Ihrer Klasse nicht abwärtskompatibel mit der vorherigen Version ist.Meistens werden Sie die Serialisierung wahrscheinlich nicht direkt verwenden. Wenn dies der Fall ist, generieren Sie einen Standard,
SerialVersionUID
indem Sie auf die Schnellkorrekturoption klicken, und machen Sie sich darüber keine Sorgen.quelle
serialVersionUID
, Sie vor inkompatiblen Änderungen zu schützen, ist gültig. Verwenden Sie@SuppressWarnings
Dokumente besser, wenn Sie die Klasse nicht für die dauerhafte Speicherung verwenden möchten.serialVersionUID
ist ein letzter Ausweg, ein Rat der Verzweiflung.Ich kann diese Gelegenheit nicht verpassen, um Josh Blochs Buch Effective Java (2nd Edition) anzuschließen . Kapitel 11 ist eine unverzichtbare Ressource für die Java-Serialisierung.
Per Josh wird die automatisch generierte UID basierend auf einem Klassennamen, implementierten Schnittstellen und allen öffentlichen und geschützten Mitgliedern generiert. Wenn Sie diese in irgendeiner Weise ändern, ändert sich die
serialVersionUID
. Sie müssen sich also nicht nur mit ihnen herumschlagen, wenn Sie sicher sind, dass nicht mehr als eine Version der Klasse jemals serialisiert wird (entweder prozessübergreifend oder zu einem späteren Zeitpunkt aus dem Speicher abgerufen).Wenn Sie sie vorerst ignorieren und später feststellen, dass Sie die Klasse auf irgendeine Weise ändern müssen, aber die Kompatibilität mit der alten Version der Klasse beibehalten müssen, können Sie mit dem JDK-Tool serialver die
serialVersionUID
für die alte Klasse generieren und diese explizit festlegen auf die neue Klasse. (Abhängig von Ihren Änderungen müssen Sie möglicherweise auch eine benutzerdefinierte Serialisierung durch HinzufügenwriteObject
undreadObject
Methoden implementieren - sieheSerializable
Javadoc oder das oben genannte Kapitel 11.)quelle
Sie können Eclipse anweisen, diese serialVersionUID-Warnungen zu ignorieren:
Falls Sie es nicht wussten, gibt es viele andere Warnungen, die Sie in diesem Abschnitt aktivieren können (oder die sogar als Fehler gemeldet werden). Viele sind sehr nützlich:
und viele mehr.
quelle
serialVersionUID
Erleichtert die Versionierung serialisierter Daten. Sein Wert wird bei der Serialisierung mit den Daten gespeichert. Bei der De-Serialisierung wird dieselbe Version überprüft, um festzustellen, wie die serialisierten Daten mit dem aktuellen Code übereinstimmen.Wenn Sie Ihre Daten versionieren möchten, beginnen Sie normalerweise mit einer
serialVersionUID
0 und stoßen sie bei jeder strukturellen Änderung Ihrer Klasse an, die die serialisierten Daten ändert (Hinzufügen oder Entfernen nicht vorübergehender Felder).Der integrierte De-Serialisierungsmechanismus (
in.defaultReadObject()
) verweigert die De-Serialisierung von alten Versionen der Daten. Wenn Sie möchten, können Sie Ihre eigene readObject () -Funktion definieren, mit der alte Daten zurückgelesen werden können. Dieser benutzerdefinierte Code kann dann überprüfen,serialVersionUID
in welcher Version sich die Daten befinden, und entscheiden, wie sie de-serialisiert werden sollen. Diese Versionierungstechnik ist nützlich, wenn Sie serialisierte Daten speichern, die mehrere Versionen Ihres Codes überleben.Das Speichern von serialisierten Daten über einen so langen Zeitraum ist jedoch nicht sehr verbreitet. Es ist weitaus üblicher, den Serialisierungsmechanismus zu verwenden, um Daten vorübergehend in beispielsweise einen Cache zu schreiben oder über das Netzwerk an ein anderes Programm mit derselben Version der relevanten Teile der Codebasis zu senden.
In diesem Fall sind Sie nicht daran interessiert, die Abwärtskompatibilität aufrechtzuerhalten. Sie müssen nur sicherstellen, dass die kommunizierenden Codebasen tatsächlich dieselben Versionen der relevanten Klassen haben. Um eine solche Überprüfung zu vereinfachen, müssen Sie das
serialVersionUID
Gleiche wie zuvor beibehalten und nicht vergessen, es zu aktualisieren, wenn Sie Änderungen an Ihren Klassen vornehmen.Wenn Sie vergessen, das Feld zu aktualisieren, erhalten Sie möglicherweise zwei verschiedene Versionen einer Klasse mit unterschiedlicher Struktur, aber derselben
serialVersionUID
. In diesem Fall erkennt der Standardmechanismus (in.defaultReadObject()
) keinen Unterschied und versucht, inkompatible Daten zu de-serialisieren. Jetzt kann es zu einem kryptischen Laufzeitfehler oder einem stillen Fehler (Nullfelder) kommen. Diese Arten von Fehlern sind möglicherweise schwer zu finden.Um diesen Anwendungsfall zu erleichtern, bietet Ihnen die Java-Plattform die Möglichkeit, die Einstellung nicht
serialVersionUID
manuell vorzunehmen . Stattdessen wird zur Kompilierungszeit ein Hash der Klassenstruktur generiert und als ID verwendet. Dieser Mechanismus stellt sicher, dass Sie niemals unterschiedliche Klassenstrukturen mit derselben ID haben, sodass diese oben erwähnten schwer nachvollziehbaren Laufzeit-Serialisierungsfehler nicht auftreten.Die automatisch generierte ID-Strategie hat jedoch einen Nachteil. Das heißt, dass sich die generierten IDs für dieselbe Klasse zwischen den Compilern unterscheiden können (wie oben von Jon Skeet erwähnt). Wenn Sie also serialisierte Daten zwischen Code kommunizieren, der mit verschiedenen Compilern kompiliert wurde, wird empfohlen, die IDs ohnehin manuell zu verwalten.
Und wenn Sie wie im ersten genannten Anwendungsfall abwärtskompatibel mit Ihren Daten sind, möchten Sie die ID wahrscheinlich auch selbst pflegen. Dies, um lesbare IDs zu erhalten und eine bessere Kontrolle darüber zu haben, wann und wie sie sich ändern.
quelle
SerialVersionUID
ist eine eindeutige Kennung für jede Klasse,JVM
mit der die Versionen der Klasse verglichen werden, um sicherzustellen, dass dieselbe Klasse während der Serialisierung verwendet wurde und während der Deserialisierung geladen wird.Wenn Sie eine angeben, erhalten Sie mehr Kontrolle, obwohl JVM eine generiert, wenn Sie keine angeben. Der generierte Wert kann zwischen verschiedenen Compilern unterschiedlich sein. Außerdem möchten Sie manchmal aus irgendeinem Grund nur die Deserialisierung alter serialisierter Objekte [
backward incompatibility
] verbieten , und in diesem Fall müssen Sie nur die serialVersionUID ändern.Die Javadocs
Serializable
sagen zum Beispiel :Daher müssen Sie serialVersionUID deklarieren, da dies uns mehr Kontrolle gibt .
Dieser Artikel enthält einige gute Punkte zum Thema.
quelle
serialVersionUID
ohne zu wissen warum. Tom Andersons Kommentar zur Antwort von MetroidFan2002 lautet wie folgt: "Ich würde sagen, wenn Sie die Serialisierung nicht für die dauerhafte Speicherung verwenden, sollten Sie @SuppressWarnings verwenden, anstatt einen Wert hinzuzufügen. Dadurch wird die Klasse weniger überladen, und die Fähigkeit der serialVersionUID-Mechanismus zum Schutz vor inkompatiblen Änderungen. "serialVersionUID
ist keine "eindeutige Kennung für jede Klasse". Der vollqualifizierte Klassenname ist das. Es ist ein Versionsindikator .In der ursprünglichen Frage wurde nach "Warum ist es wichtig" und "Beispiel" gefragt, wo dies
Serial Version ID
nützlich wäre. Nun, ich habe einen gefunden.Angenommen, Sie erstellen eine
Car
Klasse, instanziieren sie und schreiben sie in einen Objektstrom. Das abgeflachte Autoobjekt befindet sich einige Zeit im Dateisystem. In der Zwischenzeit, wenn dieCar
Klasse durch Hinzufügen eines neuen Feldes geändert wird. Wenn Sie später versuchen, das abgeflachteCar
Objekt zu lesen (dh zu deserialisieren) , erhalten Sie dasjava.io.InvalidClassException
- weil alle serialisierbaren Klassen automatisch eine eindeutige Kennung erhalten. Diese Ausnahme wird ausgelöst, wenn der Bezeichner der Klasse nicht dem Bezeichner des abgeflachten Objekts entspricht. Wenn Sie wirklich darüber nachdenken, wird die Ausnahme aufgrund des Hinzufügens des neuen Felds ausgelöst. Sie können diese Ausnahme vermeiden, indem Sie die Versionierung selbst steuern, indem Sie eine explizite serialVersionUID deklarieren. Es gibt auch einen kleinen Leistungsvorteil, wenn Sie Ihre explizit angebenserialVersionUID
(weil nicht berechnet werden muss). Es wird daher empfohlen, Ihren serialisierbaren Klassen eine eigene serialVersionUID hinzuzufügen, sobald Sie sie wie unten gezeigt erstellen:quelle
1
und so weiter.Zuerst muss ich erklären, was Serialisierung ist.
Durch die Serialisierung kann ein Objekt in einen Stream konvertiert werden, um dieses Objekt über das Netzwerk zu senden ODER in einer Datei zu speichern ODER zur Verwendung in Briefen in der Datenbank zu speichern.
Es gibt einige Regeln für die Serialisierung .
Ein Objekt ist nur dann serialisierbar, wenn seine Klasse oder seine Oberklasse die Schnittstelle Serializable implementiert
Ein Objekt ist serialisierbar (selbst implementiert die serialisierbare Schnittstelle), auch wenn seine Oberklasse dies nicht ist. Die erste Oberklasse in der Hierarchie der serialisierbaren Klasse, die keine serialisierbare Schnittstelle implementiert, MUSS jedoch einen Konstruktor ohne Argumente haben. Wenn dies verletzt wird, erzeugt readObject () zur Laufzeit eine java.io.InvalidClassException
Alle primitiven Typen sind serialisierbar.
Übergangsfelder (mit Übergangsmodifikator) werden NICHT serialisiert (dh nicht gespeichert oder wiederhergestellt). Eine Klasse, die Serializable implementiert, muss vorübergehende Felder von Klassen markieren, die keine Serialisierung unterstützen (z. B. einen Dateistream).
Statische Felder (mit statischem Modifikator) werden nicht serialisiert.
Bei der
Object
Serialisierung verknüpft Java Runtime die Serienversionsnummer aka, theserialVersionID
.Wo wir serialVersionID benötigen: Während der Deserialisierung, um zu überprüfen, ob Sender und Empfänger in Bezug auf die Serialisierung kompatibel sind. Wenn der Empfänger die Klasse mit einem anderen geladen hat,
serialVersionID
endet die Deserialisierung mitInvalidClassCastException
.Eine serialisierbare Klasse kann ihre eigene
serialVersionUID
explizit deklarieren, indem sie ein Feld mit dem Namen deklariertserialVersionUID
, das statisch, endgültig und vom Typ long sein muss.Versuchen wir dies anhand eines Beispiels.
Serialisierungsobjekt erstellen
Deserialisieren Sie das Objekt
HINWEIS: Ändern Sie nun die serialVersionUID der Employee-Klasse und speichern Sie:
Und führen Sie die Reader-Klasse aus. Wenn Sie die Writer-Klasse nicht ausführen, wird die Ausnahme angezeigt.
quelle
Wenn Sie Ihre Objekte niemals in ein Byte-Array serialisieren und senden / speichern müssen, müssen Sie sich darüber keine Gedanken machen. Wenn Sie dies tun, müssen Sie Ihre serialVersionUID berücksichtigen, da der Deserializer des Objekts sie an die Version des Objekts anpasst, über das der Klassenlader verfügt. Weitere Informationen finden Sie in der Java-Sprachspezifikation.
quelle
Wenn Sie diese Warnung für eine Klasse erhalten, an die Sie nie gedacht haben und die Sie nicht deklariert haben
implements Serializable
, liegt dies häufig daran, dass Sie von einer Oberklasse geerbt haben, die Serializable implementiert. Oft ist es dann besser, an ein solches Objekt zu delegieren, als die Vererbung zu verwenden.Also statt
tun
und in den entsprechenden Methoden
myList.foo()
anstelle vonthis.foo()
(odersuper.foo()
) aufrufen . (Dies passt nicht in allen Fällen, aber immer noch ziemlich oft.)Ich sehe oft Leute, die JFrame oder ähnliches erweitern, wenn sie wirklich nur an dieses delegieren müssen. (Dies hilft auch bei der automatischen Vervollständigung in einer IDE, da JFrame über Hunderte von Methoden verfügt, die Sie nicht benötigen, wenn Sie Ihre benutzerdefinierten Methoden in Ihrer Klasse aufrufen möchten.)
Ein Fall, in dem die Warnung (oder die serialVersionUID) unvermeidbar ist, besteht darin, dass Sie von AbstractAction aus, normalerweise in einer anonymen Klasse, nur die actionPerformed-Methode hinzufügen. Ich denke, in diesem Fall sollte es keine Warnung geben (da Sie solche anonymen Klassen normalerweise ohnehin nicht zuverlässig für verschiedene Versionen Ihrer Klasse serialisieren und deserialisieren können), aber ich bin mir nicht sicher, wie der Compiler dies erkennen könnte.
quelle
__AUTOLOAD
, von der ich nichts weiß.Um die Bedeutung des Feldes serialVersionUID zu verstehen, sollte man verstehen, wie Serialisierung / Deserialisierung funktioniert.
Wenn ein serialisierbares Klassenobjekt serialisiert wird, ordnet Java Runtime diesem serialisierten Objekt eine serielle Versionsnummer (als serialVersionUID bezeichnet) zu. Zum Zeitpunkt der Deserialisierung dieses serialisierten Objekts stimmt Java Runtime die serialVersionUID des serialisierten Objekts mit der serialVersionUID der Klasse ab. Wenn beide gleich sind, wird nur der weitere Deserialisierungsprozess fortgesetzt, andernfalls wird InvalidClassException ausgelöst.
Wir schließen daraus, dass die serialVersionUID des serialisierten Objekts der serialVersionUID der Klasse entsprechen muss, um den Serialisierungs- / Deserialisierungsprozess erfolgreich zu machen. Wenn der Programmierer den serialVersionUID-Wert explizit im Programm angibt, wird der serialisierte Objekt und die Klasse unabhängig von der Serialisierungs- und Deserialisierungsplattform derselbe Wert zugeordnet (z. B. kann die Serialisierung auf einer Plattform wie Windows mithilfe von sun oder erfolgen MS JVM und Deserialization befinden sich möglicherweise auf einer anderen Linux-Plattform (unter Verwendung von Zing JVM).
Wenn jedoch serialVersionUID vom Programmierer nicht angegeben wird, verwendet die Java-Laufzeit während der Serialisierung \ DeSerialisierung eines Objekts einen eigenen Algorithmus, um es zu berechnen. Dieser SerialVersionUID-Berechnungsalgorithmus variiert von JRE zu JRE. Es ist auch möglich, dass die Umgebung, in der das Objekt serialisiert wird, eine JRE verwendet (z. B. SUN JVM) und die Umgebung, in der die Deserialisierung erfolgt, Linux Jvm (zing) verwendet. In solchen Fällen unterscheidet sich die dem serialisierten Objekt zugeordnete serialVersionUID von der serialVersionUID der Klasse, die in der Deserialisierungsumgebung berechnet wurde. Die Deserialisierung wird wiederum nicht erfolgreich sein. Um solche Situationen / Probleme zu vermeiden, muss der Programmierer immer die serialVersionUID der Klasse Serializable angeben.
quelle
Keine Sorge, die Standardberechnung ist wirklich gut und reicht für 99.9999% der Fälle aus. Und wenn Sie auf Probleme stoßen, können Sie - wie bereits erwähnt - UIDs als Bedarfsermittlung einführen (was höchst unwahrscheinlich ist).
quelle
Ein Beispiel, bei dem die fehlende serialVersionUID ein Problem verursachen könnte:
Ich arbeite an dieser Java EE-Anwendung, die aus einem Webmodul besteht, das ein
EJB
Modul verwendet. Das Webmodul ruft dasEJB
Modul remote auf und übergibt einPOJO
, dasSerializable
als Argument implementiert wird .Diese
POJO's
Klasse wurde in das EJB-JAR und in das eigene JAR in der WEB-INF / lib des Webmoduls gepackt. Sie sind eigentlich die gleiche Klasse, aber wenn ich das EJB-Modul verpacke, entpacke ich das Glas dieses POJO, um es zusammen mit dem EJB-Modul zu verpacken.Der Anruf bei der schlug
EJB
mit der folgenden Ausnahme fehl, weil ich nicht erklärt hatteserialVersionUID
:quelle
Ich verwende
serialVersionUID
im Allgemeinen in einem Kontext: Wenn ich weiß, dass es den Kontext der Java-VM verlässt.Ich würde dies wissen, wenn ich es verwenden möchte
ObjectInputStream
undObjectOutputStream
für meine Anwendung oder wenn ich weiß, dass eine Bibliothek / ein Framework, das ich verwende, es verwenden wird. Die serialVersionID stellt sicher, dass verschiedene Java-VMs unterschiedlicher Versionen oder Anbieter ordnungsgemäß zusammenarbeiten. Wenn sie beispielsweise außerhalb der VM gespeichert und abgerufenHttpSession
werden, können die Sitzungsdaten auch während eines Neustarts und eines Upgrades des Anwendungsservers erhalten bleiben.Für alle anderen Fälle verwende ich
da die meiste Zeit die Standardeinstellung
serialVersionUID
ausreicht. Dies beinhaltetException
,HttpServlet
.quelle
Felddaten repräsentieren einige in der Klasse gespeicherte Informationen. Die Klasse implementiert die
Serializable
Schnittstelle, sodass Eclipse automatisch anbietet, dasserialVersionUID
Feld zu deklarieren . Beginnen wir mit dem dort eingestellten Wert 1.Wenn diese Warnung nicht angezeigt werden soll, verwenden Sie Folgendes:
quelle
Es wäre schön, wenn CheckStyle überprüfen könnte, ob die serialVersionUID für eine Klasse, die Serializable implementiert, einen guten Wert hat, dh mit dem übereinstimmt, was der ID-Generator für die serielle Version erzeugen würde. Wenn Sie beispielsweise ein Projekt mit vielen serialisierbaren DTOs haben und daran denken, die vorhandene serialVersionUID zu löschen und neu zu generieren, ist dies ein Problem. Derzeit ist die einzige (mir bekannte) Möglichkeit, dies zu überprüfen, die Regenerierung für jede Klasse und der Vergleich mit das Alte. Das ist sehr sehr schmerzhaft.
quelle
serialver
produzieren würde. -1serialVersionUID
auf 1. Wenn eine neuere Version der Klasse nicht kompatibel ist, aber dennoch in der Lage sein muss, mit den alten Daten umzugehen, erhöhen Sie die Versionsnummer und fügen speziellen Code hinzu beschäftigen sich mit älteren Formaten. Ich weine jedes Mal, wenn ich eineserialVersionUID
Ziffer größer als 1 sehe , entweder weil es eine Zufallszahl war (nutzlos) oder weil die Klasse anscheinend mit mehr als 10 verschiedenen Versionen umgehen muss.SerialVersionUID wird zur Versionskontrolle des Objekts verwendet. Sie können serialVersionUID auch in Ihrer Klassendatei angeben. Wenn Sie die serialVersionUID nicht angeben, kann die bereits serialisierte Klasse beim Hinzufügen oder Ändern eines Felds in der Klasse nicht wiederhergestellt werden, da die für die neue Klasse und das alte serialisierte Objekt generierte serialVersionUID unterschiedlich ist. Der Java-Serialisierungsprozess basiert auf der korrekten serialVersionUID, um den Status des serialisierten Objekts wiederherzustellen, und löst bei Nichtübereinstimmung von serialVersionUID die Ausnahme java.io.InvalidClassException aus
Lesen Sie mehr: http://javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ
quelle
Warum
SerialVersionUID
InsideSerializable
Class in Java verwenden?Während der
serialization
Java-Laufzeit wird eine Versionsnummer für eine Klasse erstellt, damit diese später de-serialisiert werden kann. Diese Versionsnummer istSerialVersionUID
in Java bekannt.SerialVersionUID
wird verwendet, um serialisierte Daten zu versionieren. Sie können eine Klasse nur de-serialisieren, wenn sieSerialVersionUID
mit der serialisierten Instanz übereinstimmt. Wenn wirSerialVersionUID
in unserer Klasse nicht deklarieren , generiert die Java-Laufzeit es für uns, aber es wird nicht empfohlen. Es wird empfohlen,SerialVersionUID
alsprivate static final long
Variable zu deklarieren , um den Standardmechanismus zu vermeiden.Wenn Sie eine Klasse wie
Serializable
durch Implementieren der Markierungsschnittstelle deklarieren,java.io.Serializable
bleibt die Java-Laufzeitinstanz dieser Klasse mithilfe des Standard-Serialisierungsmechanismus auf der Festplatte erhalten, sofern Sie den Prozess nicht über dieExternalizable
Schnittstelle angepasst haben .Siehe auch Warum SerialVersionUID in der Serializable-Klasse in Java verwenden?
quelle
Wenn Sie eine große Anzahl von Klassen ändern möchten, für die zunächst keine serialVersionUID festgelegt wurde, und gleichzeitig die Kompatibilität mit den alten Klassen beibehalten möchten, sind Tools wie IntelliJ Idea und Eclipse nicht ausreichend, da sie Zufallszahlen generieren und nicht für eine Reihe von Dateien funktionieren auf einmal. Ich rufe das folgende Bash-Skript auf (es tut mir leid für Windows-Benutzer, erwäge, einen Mac zu kaufen oder auf Linux zu konvertieren), um das Problem mit serialVersionUID mühelos zu ändern:
Wenn Sie dieses Skript speichern, sagen Sie add_serialVersionUID.sh zu Ihnen ~ / bin. Anschließend führen Sie es im Stammverzeichnis Ihres Maven- oder Gradle-Projekts wie folgt aus:
Diese .lst enthält die Liste der Java-Dateien zum Hinzufügen der serialVersionUID im folgenden Format:
Dieses Skript verwendet das JDK serialVer-Tool unter der Haube. Stellen Sie also sicher, dass sich Ihr $ JAVA_HOME / bin im PATH befindet.
quelle
Diese Frage ist in Effective Java von Joshua Bloch sehr gut dokumentiert. Ein sehr gutes Buch und ein Muss. Ich werde einige der folgenden Gründe skizzieren:
Die Serialisierungslaufzeit enthält für jede serialisierbare Klasse eine Nummer namens Serial version. Diese Nummer heißt serialVersionUID. Jetzt steckt etwas Mathematik hinter dieser Zahl und sie basiert auf den Feldern / Methoden, die in der Klasse definiert sind. Für dieselbe Klasse wird jedes Mal dieselbe Version generiert. Diese Nummer wird während der Deserialisierung verwendet, um zu überprüfen, ob der Sender und der Empfänger eines serialisierten Objekts Klassen für dieses Objekt geladen haben, die hinsichtlich der Serialisierung kompatibel sind. Wenn der Empfänger eine Klasse für das Objekt geladen hat, das eine andere serialVersionUID als die der entsprechenden Absenderklasse hat, führt die Deserialisierung zu einer InvalidClassException.
Wenn die Klasse serialisierbar ist, können Sie Ihre eigene serialVersionUID auch explizit deklarieren, indem Sie ein Feld mit dem Namen "serialVersionUID" deklarieren, das statisch, endgültig und vom Typ long sein muss. Die meisten IDEs wie Eclipse helfen Ihnen dabei, diese lange Zeichenfolge zu generieren.
quelle
Jedes Mal, wenn ein Objekt serialisiert wird, wird das Objekt mit einer Versions-ID-Nummer für die Klasse des Objekts versehen. Diese ID heißt serialVersionUID und wird basierend auf Informationen über die Klassenstruktur berechnet. Angenommen, Sie haben eine Employee-Klasse erstellt und sie hat die Versions-ID # 333 (von JVM zugewiesen). Wenn Sie nun das Objekt dieser Klasse serialisieren (Angenommen, Employee-Objekt), weist JVM ihr die UID als # 333 zu.
Stellen Sie sich eine Situation vor - in Zukunft müssen Sie Ihre Klasse bearbeiten oder ändern. In diesem Fall weist JVM ihr beim Ändern eine neue UID zu (Angenommen, Nr. 444). Wenn Sie nun versuchen, das Mitarbeiterobjekt zu deserialisieren, vergleicht JVM die Versions-ID (# 333) des serialisierten Objekts (Mitarbeiterobjekt) mit der der Klasse, dh # 444 (da es geändert wurde). Im Vergleich stellt JVM fest, dass beide UID-Versionen unterschiedlich sind und die Deserialisierung daher fehlschlägt. Daher, wenn die serialVersionID für jede Klasse vom Programmierer selbst definiert wird. Dies gilt auch dann, wenn die Klasse in Zukunft weiterentwickelt wird. Daher stellt JVM immer fest, dass die Klasse mit serialisierten Objekten kompatibel ist, obwohl die Klasse geändert wird. Weitere Informationen finden Sie in Kapitel 14 von HEAD FIRST JAVA.
quelle
serialVersionUID
wird, wird das übertragen. Es wird nicht mit jedem Objekt gesendet.Eine einfache Erklärung:
Serialisieren Sie Daten?
Bei der Serialisierung werden im Grunde Klassendaten in eine Datei / einen Stream / etc. Geschrieben. Bei der De-Serialisierung werden diese Daten in eine Klasse zurückgelesen.
Beabsichtigen Sie, in Produktion zu gehen?
Wenn Sie nur etwas mit unwichtigen / gefälschten Daten testen, machen Sie sich darüber keine Sorgen (es sei denn, Sie testen die Serialisierung direkt).
Ist das die erste Version?
Wenn ja, setzen Sie
serialVersionUID=1L
.Ist dies die zweite, dritte usw. Produktversion?
Jetzt müssen Sie sich Sorgen machen
serialVersionUID
und sollten sich eingehend damit befassen.Wenn Sie die Version beim Aktualisieren einer Klasse, die Sie schreiben / lesen müssen, nicht korrekt aktualisieren, wird im Grunde eine Fehlermeldung angezeigt, wenn Sie versuchen, alte Daten zu lesen.
quelle
'serialVersionUID' ist eine 64-Bit-Nummer, mit der eine Klasse während des Deserialisierungsprozesses eindeutig identifiziert wird. Wenn Sie ein Objekt serialisieren, wird auch die serialVersionUID der Klasse in die Datei geschrieben. Wenn Sie dieses Objekt deserialisieren, extrahiert die Java-Laufzeit diesen serialVersionUID-Wert aus den serialisierten Daten und vergleicht denselben Wert, der der Klasse zugeordnet ist. Wenn beide nicht übereinstimmen, wird 'java.io.InvalidClassException' ausgelöst.
Wenn eine serialisierbare Klasse eine serialVersionUID nicht explizit deklariert, berechnet die Serialisierungslaufzeit den serialVersionUID-Wert für diese Klasse basierend auf verschiedenen Aspekten der Klasse wie Feldern, Methoden usw. ,, Sie können diesen Link für eine Demoanwendung verwenden .
quelle
Um es kurz zu machen, dieses Feld wird verwendet, um zu überprüfen, ob serialisierte Daten korrekt deserialisiert werden können. Serialisierung und Deserialisierung werden häufig von verschiedenen Programmkopien durchgeführt. Beispielsweise konvertiert der Server das Objekt in eine Zeichenfolge und der Client konvertiert die empfangene Zeichenfolge in ein Objekt. Dieses Feld gibt an, dass beide mit derselben Vorstellung davon arbeiten, was dieses Objekt ist. Dieses Feld hilft, wenn:
Sie haben viele verschiedene Kopien Ihres Programms an verschiedenen Orten (wie 1 Server und 100 Clients). Wenn Sie Ihr Objekt ändern, Ihre Versionsnummer ändern und vergessen, einen dieser Clients zu aktualisieren, wird er wissen, dass er nicht in der Lage ist, zu deserialisieren
Sie haben Ihre Daten in einer Datei gespeichert und versuchen später, sie mit einer aktualisierten Version Ihres Programms mit geändertem Objekt zu öffnen. Sie werden wissen, dass diese Datei nicht kompatibel ist, wenn Sie Ihre Version richtig halten
Wann ist es wichtig
Am offensichtlichsten: Wenn Sie Ihrem Objekt einige Felder hinzufügen, können ältere Versionen diese nicht verwenden, da sie diese Felder nicht in ihrer Objektstruktur haben.
Weniger offensichtlich - Wenn Sie ein Objekt deserialisieren, werden Felder, die in der Zeichenfolge nicht vorhanden sind, als NULL beibehalten. Wenn Sie ein Feld aus Ihrem Objekt entfernt haben, behalten ältere Versionen dieses Feld als immer NULL bei, was zu Fehlverhalten führen kann, wenn ältere Versionen auf Daten in diesem Feld angewiesen sind (trotzdem haben Sie es für etwas erstellt, nicht nur zum Spaß :-)).
Am wenigsten offensichtlich - Manchmal ändern Sie die Idee, die Sie in die Bedeutung eines Feldes einfügen. Wenn Sie beispielsweise 12 Jahre alt sind, meinen Sie "Fahrrad" unter "Fahrrad", aber wenn Sie 18 Jahre alt sind, meinen Sie "Motorrad" - wenn Ihre Freunde Sie zu einer "Radtour durch die Stadt" einladen und Sie der einzige sind, der dies tut Wenn Sie mit dem Fahrrad gekommen sind, werden Sie verstehen, wie wichtig es ist, die gleiche Bedeutung über alle Felder hinweg beizubehalten :-)
quelle
Um Ihre Frage zu beantworten: Wenn wir SerialVersionUID in unserer Klasse nicht deklarieren, generiert die Java-Laufzeit diese für uns. Dieser Prozess reagiert jedoch empfindlich auf viele Klassen-Metadaten, einschließlich Anzahl der Felder, Feldtyp, Zugriffsmodifikator für Felder und implementierte Schnittstelle nach Klasse usw. Daher wird empfohlen, es selbst zu deklarieren, und Eclipse warnt Sie davor.
Serialisierung: Wir arbeiten häufig mit wichtigen Objekten, deren Status (Daten in den Variablen des Objekts) so wichtig ist, dass wir nicht riskieren können, sie aufgrund von Strom- / Systemfehlern (oder Netzwerkfehlern) zu verlieren, wenn der Objektstatus an andere gesendet wird Maschine. Die Lösung für dieses Problem heißt "Persistenz", was einfach bedeutet, dass die Daten beibehalten (gehalten / gespeichert) werden. Die Serialisierung ist eine von vielen anderen Möglichkeiten, um Persistenz zu erreichen (durch Speichern von Daten auf Festplatte / Speicher). Beim Speichern des Objektstatus ist es wichtig, eine Identität für das Objekt zu erstellen, um es ordnungsgemäß zurücklesen zu können (De-Serialisierung). Diese eindeutige Identifikation lautet ID ist SerialVersionUID.
quelle
Was ist SerialVersionUID? Antwort: - Nehmen wir an, es gibt zwei Personen, eine vom Hauptquartier und eine vom ODC. Beide werden eine Serialisierung bzw. Deserialisierung durchführen. In diesem Fall erstellt JVM eine eindeutige ID, die als SerialVersionUID bezeichnet wird, um zu authentifizieren, dass der Empfänger in ODC die authentifizierte Person ist.
Hier ist eine schöne Erklärung basierend auf dem Szenario:
Warum SerialVersionUID?
Serialisierung : Zum Zeitpunkt der Serialisierung speichert JVM mit jeder Objektsenderseite eine eindeutige Kennung. JVM ist dafür verantwortlich, diese eindeutige ID basierend auf der entsprechenden .class-Datei zu generieren, die im Absendersystem vorhanden ist.
Deserialisierung : Zum Zeitpunkt der Deserialisierung vergleicht die empfängerseitige JVM die dem Objekt zugeordnete eindeutige ID mit der lokalen Klasse. Eindeutige ID, dh JVM erstellt auch eine eindeutige ID basierend auf der entsprechenden .class-Datei, die im Empfängersystem vorhanden ist. Wenn beide eindeutigen IDs übereinstimmen, wird nur eine Deserialisierung durchgeführt. Andernfalls erhalten wir eine Laufzeitausnahme mit der Aufschrift InvalidClassException. Diese eindeutige Kennung ist nichts anderes als SerialVersionUID
quelle