Frage

Eclipse gibt Warnungen aus, wenn a serialVersionUID wird vermisst.

Die serialisierbare Klasse Foo deklariert kein statisches endgültiges serialversionuides Feld vom Typ Long

Was ist serialVersionUID und warum ist es wichtig?Bitte zeigen Sie ein Beispiel, wo etwas fehlt serialVersionUID wird ein Problem verursachen.

War es hilfreich?

Lösung

Die Dokumentation für java.io.Serializable sind wahrscheinlich so gut, eine Erklärung, wie Sie erhalten:

  

Die Serialisierung Runtime ordnet jede serializable Klasse eine Versionsnummer, ein serialVersionUID genannt, die bei der Deserialisierung verwendet wird, um zu überprüfen, dass der Sender und Empfänger eines serialisierten Objekt haben für diese Objektklassen geladen, die in Bezug auf der Serialisierung kompatibel sind. Wenn der Empfänger eine Klasse für das Objekt geladen ist, die eine andere serialVersionUID als die des entsprechenden Senders Klasse hat, dann wird die Deserialisierung in einer Folge    InvalidClassException . Eine serializable Klasse kann seine eigene serialVersionUID erklären ausdrücklich durch ein Feld namens serialVersionUID erklärt, die statisch sein müssen, endgültig und vom Typ long:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
     

Wenn eine serializable Klasse nicht explizit ein serialVersionUID erklären, dann ist die Serialisierung Laufzeit wird für diese Klasse eines Standard serialVersionUID Wert berechnen, basierend auf verschiedenen Aspekten der Klasse, wie in der Java (TM) Objektserialisierung Spezifikation beschrieben. Es ist jedoch dringend empfohlen , dass alle serializable Klassen explizit serialVersionUID Werte, da die Standard serialVersionUID Berechnung ist sehr empfindlich gegenüber Klasse Details erklären, die auf Compiler-Implementierungen variieren abhängig und somit in unerwarteten InvalidClassExceptions während der Deserialisierung führen können . Daher einen konsistenten serialVersionUID Wert über verschiedene Java-Compiler-Implementierungen zu gewährleisten, muss eine serialisierbare Klasse einen expliziten serialVersionUID Wert. Es wird auch dringend empfohlen, dass explizite serialVersionUID Erklärungen den privaten Modifikator wo möglich verwenden, da solche Erklärungen gelten nur für die unmittelbar deklarierte Klasse serialVersionUID Felder sind nicht geeignet als geerbten Mitglieder.

Andere Tipps

Wenn Sie die Serialisierung, nur weil Sie für die Durchführung willen serialisiert haben (wer kümmert sich, wenn Sie eine HTTPSession serialisiert, zum Beispiel ... wenn sie gespeichert sind oder nicht, werden Sie wahrscheinlich nicht kümmern uns um de-serializing ein Formularobjekt ), dann können Sie diese ignorieren.

Wenn Sie tatsächlich Serialisierung verwenden, ist es nur wichtig, wenn Sie auf das Speichern und Abrufen von Objekten direkt mit Serialisierung. Die serialVersionUID stellt Ihre Klasse-Version, und Sie sollten es erhöhen, wenn die aktuelle Version Ihrer Klasse nicht rückwärts kompatibel mit der Vorgängerversion ist.

Die meisten der Zeit, werden Sie wahrscheinlich Serialisierung nicht direkt verwenden. Wenn dies der Fall ist, erzeugt einen Standard SerialVersionUID durch die schnelle Lösung Option anklicken und keine Sorge über sie.

Ich kann diese Gelegenheit nicht entgehen lassen Josh Blochs Buch Effective Java Plug (2nd Edition). Kapitel 11 ist ein unverzichtbares Hilfsmittel auf Java Serialisierung.

Per Josh, der automatisch generierte UID basiert auf einer Klassennamen erzeugt, implementiert Schnittstellen und alle öffentlichen und geschützten Mitglieder. jeder dieser in irgendeiner Weise ändern, wird die serialVersionUID ändern. Sie brauchen also nicht mit ihnen zu verwirren nur, wenn Sie sicher sind, dass nicht mehr als eine Version der Klasse jemals serialisiert werden (entweder über Prozesse oder aus dem Speicher zu einem späteren Zeitpunkt abgerufen werden).

Wenn Sie sie jetzt zu ignorieren, und finden später, die Sie benötigen, die Klasse in irgendeiner Weise zu ändern, aber die Kompatibilität w / alte Version der Klasse, können Sie das JDK-Tool serialver zu erzeugen, die serialVersionUID auf dem alt Klasse und ausdrücklich festgelegt, dass auf die neue Klasse. (Je nach Änderungen benötigen Sie können auch benutzerdefinierte Serialisierung zu implementieren, indem writeObject und readObject Methoden hinzufügen -. Serializable javadoc oder vorher erwähnten siehe Kapitel 11)

Sie können Eclipse-sagen diese serialVersionUID Warnungen zu ignorieren:

  

Fenster> Einstellungen> Java> Compiler> Fehler / Warnungen> Mögliche Programmierung Probleme

Falls Sie nicht wissen, gibt es eine Menge anderer Warnungen, die Sie in diesem Abschnitt aktivieren können (oder sogar haben einige als Fehler gemeldet), viele sind sehr nützlich:

  • Mögliche Programmierung Probleme: Mögliche versehentliche boolean Zuordnung
  • Mögliche Programmierung Probleme: Null-Zeiger-Zugriff
  • Unnötige Code: Lokale Variable wird nie gelesen
  • Unnötige Code: Redundante null Prüfung
  • Unnötige Code: Unnötige Guss- oder 'instanceof'

und viele mehr.

serialVersionUID erleichtert Versionierung von serialisierten Daten. Sein Wert wird mit dem Daten gespeichert sind, wenn die Serialisierung. Nach Abwahl Serialisierung wird die gleiche Version geprüft, um zu sehen, wie die serialisierten Daten den aktuellen Code entspricht.

Wenn Sie auf die Version Ihrer Daten möchten, können Sie normalerweise mit einem serialVersionUID von 0 beginnen, und stoßen sie mit jeder strukturellen Änderung Ihrer Klasse, die die serialisierten Daten (Hinzufügen oder Entfernen von nicht-transienten Felder) verändert.

Der eingebaute in de-Serialisierungsmechanismus (in.defaultReadObject()) wird sich weigern, von den alten Versionen der Daten Deserialisieren. Aber wenn Sie wollen, können Sie Ihre eigenen readObject- () -function die alten Daten zurückgelesen werden. Dieser benutzerdefinierte Code kann dann überprüfen Sie die serialVersionUID, um zu wissen, welche Version der Daten in und zu entscheiden, wie es deserialisieren. Diese Versionierung Technik ist nützlich, wenn Sie serialisierten Daten speichern, die mehrere Versionen des Codes überlebt.

Aber Speicherung serialisierten Daten für eine solche Zeitspanne lange Zeit ist nicht sehr verbreitet. Es ist weitaus häufiger den Serialisierung-Mechanismus zu verwenden, um vorübergehend Daten zu schreiben, um zum Beispiel eines Cache oder über das Netzwerk mit der gleichen Version der relevanten Teile der Code-Basis an ein anderes Programm senden.

In diesem Fall sind Sie nicht daran interessiert, die Abwärtskompatibilität beibehalten. Sie sind nur mit dafür sorgen, dass die Code-Basen, die in der Tat die gleichen Versionen der relevanten Klassen kommunizieren. Um eine solche Prüfung zu erleichtern, müssen Sie die serialVersionUID wie vor halten und nicht zu vergessen, es zu aktualisieren, wenn Änderungen an Klassen zu machen.

Wenn Sie vergessen, das Feld zu aktualisieren, könnte man mit zwei verschiedenen Versionen einer Klasse mit unterschiedlichen Struktur am Ende aber mit dem gleichen serialVersionUID. Wenn dies der Fall ist, erkennt der Standardmechanismus (in.defaultReadObject()) keinen Unterschied, und versuchen, inkompatible Daten deserialisieren. Nun könnte man mit einem kryptischen Laufzeitfehler oder stillen Fehlern (Null-Felder) enden. Diese Art von Fehler könnte sein, schwer zu finden.

So diese usecase zu helfen, die Java-Plattform bietet Ihnen eine Auswahl von nicht serialVersionUID manuell einstellen. Stattdessen wird ein Hash-Wert der Klassenstruktur zur Compile-Zeit und als ID verwendet erzeugt werden. Dieser Mechanismus wird sicherstellen, dass Sie nie unterschiedliche Klassenstrukturen mit der gleichen ID haben, und so werden Sie nicht diese schwer zu Trace Runtime Serialisierung Ausfälle oben erwähnt erhalten.

Aber es gibt eine Kehrseite an die automatisch generierte ID-Strategie. Das heißt, dass die erzeugten IDs für dieselbe Klasse könnte zwischen Compilern unterscheiden (wie durch Jon Skeet oben erwähnt). Also, wenn Sie serialisierten Daten zwischen mit verschiedenen Compilern kompilierten Code kommunizieren, empfiehlt es sich auf jeden Fall die IDs manuell zu pflegen.

Und wenn Sie rückwärts kompatibel sind mit Ihren Daten wie in dem ersten Anwendungsfall erwähnt, auch wollen Sie wahrscheinlich die ID selbst zu halten. Dies deshalb, um lesbar ids zu bekommen und haben eine größere Kontrolle darüber, wann und wie sie sich verändern.

  

Was ist ein serialVersionUID und warum sollte ich es verwenden?

SerialVersionUID ist eine eindeutige Kennung für jede Klasse, JVM verwendet es die Versionen der Klasse vergleichen sicherzustellen, dass die gleiche Klasse während der Serialisierung verwendet wurde, wird während der Deserialisierung geladen.

eine Angabe gibt mehr Kontrolle, obwohl JVM ein generiert, wenn Sie nicht angeben. Der erzeugte Wert kann zwischen verschiedenen Compilern unterscheiden. Darüber hinaus manchmal möchte man einfach aus irgendeinem Grund Deserialisierung von alten serialisierte Objekte zu verbieten [backward incompatibility], und in diesem Fall müssen Sie nur noch die serialVersionUID ändern.

Die javadocs für Serializable sagen :

  

die Standard serialVersionUID Berechnung ist sehr empfindlich gegenüber Klasse   Details, die je nach Compiler-Implementierungen variieren und können   Damit ergeben sich in unerwarteten InvalidClassExceptions während   Deserialisierung.

Aus diesem Grund müssen Sie serialVersionUID erklären, weil es uns mehr Kontrolle .

diesem Artikel einige gute Punkte zum Thema hat.

Original Frage wird gefragt: ‚Warum ist es wichtig‘ und ‚Beispiel‘ wenn dies Serial Version ID nützlich wäre. Nun, ich habe eine gefunden.

Sagen Sie bitte eine Car Klasse erstellen, instanziiert, und es schreiben, um ein Objekt ausströmen. Der abgeflachte Auto Objekt befindet sich in dem Dateisystem für einige Zeit. Unterdessen wird, wenn die Car Klasse durch Hinzufügen eines neuen Feldes geändert. Später, wenn Sie versuchen, lesen (das heißt deserialize), um das abgeflachte Car Objekt, erhalten Sie die java.io.InvalidClassException - weil alle serializable Klassen automatisch eine eindeutige Kennung gegeben. Diese Ausnahme wird ausgelöst, wenn die Bezeichner der Klasse, die nicht gleich die Kennung des abgeflachten Objekts ist. Wenn Sie wirklich darüber nachdenkt, wird die Ausnahme aufgrund der Zugabe des neuen Feldes geworfen. Sie können diese Ausnahme durch geworfen vermeiden Steuerung der selbst Versionierung durch eine explizite serialVersionUID erklärt. Es gibt auch einen kleinen Leistungsvorteil in Ihrem serialVersionUID ausdrücklich erklärt (weil nicht berechnet werden muß). So ist es am beste Praxis, um Ihre eigene serialVersionUID zu Ihrer Serializable Klasse hinzuzufügen, sobald Sie sie erstellen, wie unten dargestellt:

public class Car {
    static final long serialVersionUID = 1L; //assign a long value
}

Wenn Sie nie Ihre Objekte Byte-Array serialisiert werden müssen und senden / speichern sie, dann brauchen Sie nicht zu kümmern. Wenn Sie das tun, dann müssen Sie Ihre serialVersionUID betrachten, da die Deserializer des Objekts werden auf die Version des Objekts entsprechen sein Classloader hat. Lesen Sie mehr darüber in der Java Language Specification.

Wenn Sie diese Warnung auf einer Klasse erhalten Sie jemals über die Serialisierung nicht denken, und dass Sie nicht erklären, selbst implements Serializable, ist es oft, weil man von einer übergeordneten Klasse geerbt, die Serializable implementiert. Oft dann wäre es besser, auf ein solches Objekt zu übertragen, anstatt Vererbung verwendet wird.

Also, statt

public class MyExample extends ArrayList<String> {

    public MyExample() {
        super();
    }
    ...
}

do

public class MyExample {
    private List<String> myList;

    public MyExample() {
         this.myList = new ArrayList<String>();
    }
    ...
}

und in den einschlägigen Methoden aufrufen myList.foo() statt this.foo() (oder super.foo()). (Dies gilt nicht in allen Fällen passen, aber immer noch recht häufig.)

ich oft Leute sehen, erstreckt JFrame oder solche, wenn sie wirklich nur auf diese delegieren müssen. (Dies hilft auch bei einer IDE-Auto-Vervollständigung, da JFrame Hunderte von Methoden hat, die Sie nicht brauchen, wenn Sie möchten, dass Ihre Gewohnheit ein auf Ihrer Klasse nennen.)

Ein Fall, in dem die Warnung (oder die serialVersionUID) unvermeidbar ist, wenn Sie von Abstract verlängern, in der Regel in einer anonymen Klasse, nur die actionPerformed-Methode hinzugefügt wird. Ich denke, es nicht eine Warnung in diesem Fall sein sollte (da Sie in der Regel nicht als zuverlässig serialize und deserialisieren solche anonymen Klassen sowieso accross verschiedene Versionen Ihrer Klasse), aber ich bin mir nicht sicher, wie der Compiler dies erkennen kann.

die Bedeutung des Feldes serialVersionUID Um zu verstehen, sollte man verstehen, wie Serialisierung / Deserialisierung funktioniert.

Wenn ein Serializable Klasse Objekt serialisiert wird Java Runtime ordnet eine serielle Version Nr. (Genannt als serialVersionUID) mit diesem serialisierten Objekt. Zu der Zeit, wenn Sie deserialisieren dieses serialisierte Objekt Java Runtime entspricht den serialVersionUID von serialisierten Objekt mit der serialVersionUID der Klasse. Wenn beide gleich sind, dann nur geht es mit dem weiteren Prozess der Deserialisierung sonst wirft InvalidClassException.

So wir schließen, dass zu Serialisierung / Deserialisierung Prozess erfolgreich die serialVersionUID von serialisierten Objekt machen muß das serialVersionUID der Klasse entspricht. Im Fall, wenn Programmierer den serialVersionUID Wert explizit im Programm gibt dann dem gleichen Wert wird mit dem serialisierten Objekt und der Klasse, unabhängig von der Serialisierung und deserialzation Plattform (zB in Verbindung gebracht werden. Serialisierung auf der Plattform wie Fenster, indem Sie Sonne getan werden könnte, oder MS JVM und Deserialisierung auf verschiedene Linux-Plattform sein könnten Zing JVM).

Aber für den Fall, wenn serialVersionUID nicht vom Programmierer festgelegt dann während Serialisierung \ Deserialisierung eines Objekts zu tun, Java-Runtime verwendet einen eigenen Algorithmus es zu berechnen. Dieser serialVersionUID Berechnungsalgorithmus variiert von JRE zu einem anderen. Es ist auch möglich, dass die Umgebung, in der das Objekt serialisiert wird, wird mit einem JRE (ex: SUN JVM) und der Umgebung, in deserialzation geschieht unter Verwendung von Linux Jvm (Zing). In solchen Fällen serialVersionUID mit serialisierten Objekt zugeordnet wird als der serialVersionUID der Klasse bei deserialzation Umgebung berechnet unterschiedlich sein. Im Gegenzug Deserialisierung wird nicht erfolgreich sein. So solche Situationen / Themen Programmierer zu vermeiden, muss immer serialVersionUID von Serializable Klasse angeben.

Zuerst muss ich die Serialisierung erklären.
Serialisierung Ermöglicht die Konvertierung des Objekts in einen Stream, um es über das Netzwerk zu senden ODER das Speichern in einer Datei ODER das Speichern in der Datenbank zur Briefverwendung.

Es gibt einige Regeln für die Serialisierung.

  • Ein Objekt ist nur dann serialisierbar, wenn seine Klasse oder seine Oberklasse die Serializable-Schnittstelle implementiert

  • Ein Objekt ist serialisierbar (implementiert selbst die Serializable-Schnittstelle), auch wenn seine Oberklasse dies nicht ist.Allerdings MUSS die erste Superklasse in der Hierarchie der serialisierbaren Klasse, die die serialisierbare Schnittstelle nicht implementiert, über einen Konstruktor ohne Argumente verfügen.Wenn dies verletzt wird, erzeugt readObject() zur Laufzeit eine java.io.InvalidClassException

  • Alle primitiven Typen sind serialisierbar.

  • Transiente Felder (mit Transient-Modifikator) werden NICHT serialisiert (d. h. nicht gespeichert oder wiederhergestellt).Eine Klasse, die Serializable implementiert, muss transiente Felder von Klassen markieren, die keine Serialisierung unterstützen (z. B. einen Dateistream).

  • Statische Felder (mit statischem Modifikator) werden nicht serialisiert.

Wenn das Objekt serialisiert ist, ordnet JAVA Runtime die serielle Versionsnummer zu, die als serialVersionID bezeichnet wird.

Wo wir serialVersionID brauchen: Während der Deserialisierung wird überprüft, ob Sender und Empfänger hinsichtlich der Serialisierung kompatibel sind. Wenn der Empfänger die Klasse mit einer anderen serialVersionID geladen hat, wird die Deserialisierung mit beendet InvalidClassCastException.
Eine serialisierbare Klasse kann ihre eigene serialVersionUID explizit deklarieren, indem sie ein Feld namens „serialVersionUID“ deklariert, das statisch, final und vom Typ long: sein muss.

Versuchen wir es anhand eines Beispiels.

import java.io.Serializable;    
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String empname;
private byte empage;

public String getEmpName() {
    return name;
}
public void setEmpName(String empname) {
    this.empname = empname;
}
public byte getEmpAge() {
    return empage;
}
public void setEmpAge(byte empage) {
    this.empage = empage;
}

public String whoIsThis() {
    StringBuffer employee = new StringBuffer();
    employee.append(getEmpName()).append(" is ).append(getEmpAge()).append("
years old  "));
    return employee.toString();
}
}

Erstellen Sie ein Serialisierungsobjekt

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Writer {
public static void main(String[] args) throws IOException {
    Employee employee = new Employee();
    employee.setEmpName("Jagdish");
    employee.setEmpAge((byte) 30);

    FileOutputStream fout = new 
FileOutputStream("/users/Jagdish.vala/employee.obj");
    ObjectOutputStream oos = new ObjectOutputStream(fout);
    oos.writeObject(employee);
    oos.close();
    System.out.println("Process complete");
}
}

Deserialisieren Sie das Objekt

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Reader {
public static void main(String[] args) throws ClassNotFoundException, 
IOException {
    Employee employee = new Employee();
    FileInputStream fin = new 
    FileInputStream("/users/Jagdish.vala/employee.obj");
    ObjectInputStream ois = new ObjectInputStream(fin);
    employee = (Employee) ois.readObject();
    ois.close();
    System.out.println(employee.whoIsThis());
 }
}    

NOTIZ:Ändern Sie nun die serialVersionUID der Employee-Klasse und speichern Sie:

private static final long serialVersionUID = 4L;

Und führen Sie die Reader-Klasse aus.Wenn Sie die Writer-Klasse nicht ausführen, erhalten Sie die Ausnahme.

Exception in thread "main" java.io.InvalidClassException: 
com.jagdish.vala.java.serialVersion.Employee; local class incompatible: 
stream classdesc serialVersionUID = 1, local class serialVersionUID = 4
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.krishantha.sample.java.serialVersion.Reader.main(Reader.java:14)

Sie sich nicht die Mühe, ist die Standard-Berechnung wirklich gut und für 99,9999% der Fälle ausreichen. Und wenn Sie Probleme, Sie können - wie bereits erwähnt - Einführung UID als die Notwendigkeit arrise (was sehr unwahrscheinlich ist)

Als ein Beispiel, wo das fehlende serialVersionUID ein Problem verursachen könnte:

Ich arbeite an dieser Java EE-Anwendung, die von einem Web-Modul zusammengesetzt ist, die einen EJB Modul verwendet. Der Web-Modul ruft den EJB Modul remote und übergibt eine POJO die Serializable als Argument implementiert.

Diese POJO's Klasse wurde in der EJB jar verpackt und innerhalb seiner eigenen jar im WEB-INF / lib des Web-Moduls. Sie sind eigentlich die gleiche Klasse, aber wenn ich die EJB-Modul-Paket ich entpacken Sie dieses Bild Glas des POJO es zu packen zusammen mit dem EJB-Modul.

Der Aufruf des EJB mit der Ausnahme unten versagt, weil ich nicht seinen serialVersionUID erklärt hatte:

Caused by: java.io.IOException: Mismatched serialization UIDs : Source
 (Rep.
 IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588)
 = 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52)
 = 6227F23FA74A9A52

Ich verwende serialVersionUID im Allgemeinen in einem Kontext: Wenn ich weiß, wird es den Kontext der Java VM verlassen.

Ich würde dies wissen, wenn ich ObjectInputStream und ObjectOutputStream für meine Anwendung zu verwenden, oder wenn ich eine Bibliothek / Rahmen weiß ich sie verwenden. Die serialVersionID sorgt für verschiedenen Java VMs von Versionen oder Anbieter unterschiedlicher wird inter korrekt funktionieren oder ob es gespeichert und außerhalb der VM zum Beispiel HttpSession die Sitzungsdaten können auch während eines Neustarts und Upgrade des Anwendungsservers.

bleiben abgerufen

Für alle anderen Fälle, verwende ich

@SuppressWarnings("serial")

da die meiste Zeit der Standard serialVersionUID ausreichend. Dazu gehören Exception, HttpServlet.

Felddaten repräsentieren einige Informationen in der Klasse gespeichert. Klasse implementiert die Serializable Schnittstelle, so eclipse automatisch angeboten, um das serialVersionUID Feld zu erklären. Fangen wir mit Wert 1 gesetzt dort beginnen.

Wenn Sie nicht, dass die Warnung kommen wollen, verwenden Sie diese:

@SuppressWarnings("serial")

SerialVersionUID wird für die Versionskontrolle des Objekts verwendet. Sie können auch serialVersionUID in Ihrer Klasse-Datei angeben. Consequence von nicht serialVersionUID Angabe ist, dass, wenn Sie ein beliebiges Feld in der Klasse hinzufügen oder ändern dann bereits serialisierten Klasse nicht in der Lage sein, sich zu erholen, weil serialVersionUID für neue Klasse erzeugt und für alte serialisierte Objekt wird anders sein. Java Serialisierung auf korrekte serialVersionUID verlässt sich für den Zustand des serialisierten Objekts erholt und wirft java.io.InvalidClassException bei serialVersionUID Mismatch

Lesen Sie mehr: http://javarevisited.blogspot.com/ 2011/04 / Top-10-java-Serialisierung-interview.html # ixzz3VQxnpOPZ

Es wäre schön, wenn die Check dass serialVersionUID auf eine Klasse überprüfen könnte, die Serializable hat einen guten Wert implementiert, das heißt, dass es übereinstimmt, was die Serienversion id Generator erzeugen würde. Wenn Sie ein Projekt mit vielen serializable DTOs zum Beispiel der Erinnerung an die bestehende serialVersionUID zu löschen und regeneriert es ein Schmerz ist, und zur Zeit der einzige Weg, (die ich kenne), um sicherzustellen, dies für jede Klasse zu regenerieren und zu vergleichen, um das Alte. Das ist sehr, sehr schmerzhaft.

Warum Gebrauch SerialVersionUID innerhalb Serializable Klasse in Java?

Während serialization erstellt Java-Runtime eine Versionsnummer für eine Klasse, so dass er es später deserialisieren. Diese Versionsnummer ist bekannt als SerialVersionUID in Java.

SerialVersionUID wird auf Version serialisiert Daten verwendet. Sie können nur eine Klasse Deserialisieren wenn es SerialVersionUID ist übereinstimmt mit der serialisierten Instanz. Wenn wir nicht SerialVersionUID in unserer Klasse deklarieren, Java-Laufzeit generiert es für uns, aber es ist nicht zu empfehlen. Es wird empfohlen, SerialVersionUID als private static final long Variable zu deklarieren Standardmechanismus zu vermeiden.

Wenn Sie eine Klasse als Serializable erklären durch Marker-Schnittstelle java.io.Serializable Implementierung Java-Runtime beharrt Instanz dieser Klasse in der Disk standardmäßig Serialisierung Mechanismus verwenden, vorausgesetzt, Sie haben nicht den Prozess mit Externalizable Schnittstelle angepasst werden.

siehe auch Warum Gebrauch serialVersionUID innerhalb Serializable Klasse in Java

Code: javassist.SerialVersionUID

Wenn Sie eine große Anzahl von Klassen ändern möchten, die keine serialVersionUID an erster Stelle gesetzt hatte, während die Kompatibilität mit den alten Klassen zu halten, Tools wie IntelliJ Idea, fallen Eklipse kurz wie sie Zufallszahlen zu erzeugen und funktioniert nicht auf ein Reihe von Dateien in einem Rutsch. Ich komme den folgenden Bash-Skript (ich bin für Windows-Anwender leid, sollten Sie einen Mac kaufen oder zu Linux konvertieren) zu serialVersionUID Problems mit Leichtigkeit Änderung:

base_dir=$(pwd)                                                                  
src_dir=$base_dir/src/main/java                                                  
ic_api_cp=$base_dir/target/classes                                               

while read f                                                                     
do                                                                               
    clazz=${f//\//.}                                                             
    clazz=${clazz/%.java/}                                                       
    seruidstr=$(serialver -classpath $ic_api_cp $clazz | cut -d ':' -f 2 | sed -e 's/^\s\+//')
    perl -ni.bak -e "print $_; printf qq{%s\n}, q{    private $seruidstr} if /public class/" $src_dir/$f
done

Sie dieses Skript speichern, sagen add_serialVersionUID.sh Sie ~ / bin. Dann Sie es im Stammverzeichnis Ihres Maven oder Gradle Projekt wie ausführen:

add_serialVersionUID.sh < myJavaToAmend.lst

Diese LST enthält die Liste der Java-Dateien, die serialVersionUID in folgendem Format hinzuzufügen:

com/abc/ic/api/model/domain/item/BizOrderTransDO.java
com/abc/ic/api/model/domain/item/CardPassFeature.java
com/abc/ic/api/model/domain/item/CategoryFeature.java
com/abc/ic/api/model/domain/item/GoodsFeature.java
com/abc/ic/api/model/domain/item/ItemFeature.java
com/abc/ic/api/model/domain/item/ItemPicUrls.java
com/abc/ic/api/model/domain/item/ItemSkuDO.java
com/abc/ic/api/model/domain/serve/ServeCategoryFeature.java
com/abc/ic/api/model/domain/serve/ServeFeature.java
com/abc/ic/api/model/param/depot/DepotItemDTO.java
com/abc/ic/api/model/param/depot/DepotItemQueryDTO.java
com/abc/ic/api/model/param/depot/InDepotDTO.java
com/abc/ic/api/model/param/depot/OutDepotDTO.java

Dieses Skript verwendet das JDK serialver-Tool unter der Motorhaube. So stellen Sie sicher, dass Ihr $ JAVA_HOME / bin im PATH ist.

Diese Frage ist sehr gut in Effective Java von Joshua Bloch dokumentiert. Ein sehr gutes Buch und ein Muss lesen. Ich werde einige der Gründe umreißen unten:

Die Serialisierung Laufzeit wird mit einer Reihe genannt Serienversion für jede serializable Klasse auf. Diese Nummer wird serialVersionUID genannt. Jetzt gibt es einige Mathe hinter dieser Zahl und es herauskommt, basierend auf den Feldern / Methoden, die in der Klasse definiert sind. Für die gleiche Klasse ist die gleiche Version jedes Mal erzeugt. Diese Nummer wird während der Deserialisierung verwendet, um zu überprüfen, dass der Sender und Empfänger einer serialisierten Objektklassen geladen haben für das Objekt, das in Bezug auf die Serialisierung kompatibel sind. Wenn der Empfänger eine Klasse für das Objekt geladen ist, die eine andere serialVersionUID als die des entsprechenden Senders Klasse hat, dann wird die Deserialisierung in einem InvalidClassException zur Folge hat.

Wenn die Klasse serialisierbar ist, dass Sie auch Ihre eigene serialVersionUID ausdrücklich, indem er erklärt ein Feld „serialVersionUID“ genannt erklären können, die lange statisch, endgültig und vom Typ sein müssen. Die meisten IDE wie Eclipse-Hilfe erzeugen Sie, dass die lange Zeichenfolge.

Jedes Mal, wenn ein Objekt, das Objekt serialisiert wird, wird für die class.This ID des Objekts mit einer Version ID-Nummer gestempelt genannt wird serialVersionUID und wird berechnet basierend auf Informationen über die Klassenstruktur. Angenommen, Sie eine Klasse Employee gemacht und es hat Version ID # 333 (von JVM zugewiesen), jetzt, wenn Sie das Objekt dieser Klasse (Angenommen Employee-Objekt) serialisiert werden, JVM UID, um es als # 333 zuweisen wird.

eine Situation betrachtet - in der Zukunft, die Sie benötigen, um Ihre Klasse zu bearbeiten oder zu ändern, und in diesem Fall, wenn Sie es ändern, JVM weisen Sie eine neue UID (Angenommen, # 444). Nun, wenn Sie versuchen, die Mitarbeiter Objekt deserialisiert wird JVM serialisierten Objekt vergleichen (Employee-Objekt) Version ID (# 333) mit dem der Klasse d.h # 444 (Da es geändert wurde). Beim Vergleich wird JVM finden beide Version UID sind unterschiedlich und daher wird Deserialisierung fehlschlagen. Daher, wenn serialVersionID für jede Klasse wird durch Programmierer selbst definiert. Es wird gleich sein, auch wenn die Klasse in Zukunft weiterentwickelt wird und somit wird JVM findet immer, dass die Klasse mit serialisierten Objekt kompatibel ist, obwohl die Klasse geändert wird. Für weitere Informationen können Sie Kapitel 14 von HEAD FIRST JAVA beziehen.

eine einfache Erklärung:

  1. Sind Sie Serialisierung Daten?

    Serialisierung schreibt grundsätzlich Klassendaten in einer Datei / Strom / etc. De-Serialisierung ist, dass die Daten zu einer Klasse lesen zurück.

  2. Wollen Sie in die Produktion gehen?

    Wenn Sie nur etwas mit unwichtigen / gefälschten Daten zu testen sind, dann nicht darum kümmern (es sei denn, Sie Serialisierung testen direkt).

  3. Ist dies die erste Version?

    Wenn ja, setzen serialVersionUID=1L.

  4. Ist dies die zweite, dritte usw. prod Version?

    Jetzt müssen Sie über serialVersionUID kümmern, und hinein in die Tiefe aussehen sollte.

Grundsätzlich, wenn Sie die Version nicht korrekt aktualisiert, wenn Sie eine Klasse aktualisieren Sie schreiben müssen / lesen, werden Sie eine Fehlermeldung erhalten, wenn Sie versuchen, alte Daten zu lesen.

die lange Geschichte zu erzählen, kurz dieses Feld verwendet wird, um zu überprüfen, ob serialisierten Daten korrekt deserialisiert werden kann. Serialisierung und Deserialisierung werden oft von verschiedenen Kopien Programm gemacht - zum Beispiel Server-Objekt in String konvertiert und Client wandelt empfangene Zeichenfolge zu widersprechen. Dieses Feld sagt, dass beide arbeiten mit dem gleichen Vorstellung davon, was dieses Objekt. Dieses Feld hilft, bei der:

  • Sie viele verschiedene Kopien des Programms haben in verschiedenen Orten (wie 1-Server und 100 Clients). Wenn Sie Ihr Objekt ändern, ändern Sie Ihre Versionsnummer und vergisst man diese Clients zu aktualisieren, wird es wissen, dass er nicht in der Lage Deserialisierung ist

  • Sie Ihre Daten in irgendeiner Datei gespeichert und später auf Sie versuchen, mit aktualisierten Version des Programms zu öffnen, es mit modifizierten Objekt - Sie wissen, dass diese Datei nicht kompatibel ist, wenn Sie Ihre Version rechts halten

Wann ist es wichtig?

Am offensichtlichsten -., Wenn Sie einige Felder zu Ihrem Objekt hinzufügen, ältere Versionen werden nicht in der Lage sein, sie zu benutzen, weil sie diese Felder nicht in ihrer Objektstruktur haben

Weniger offensichtlich - Wenn Sie Objekt deserialisieren, Felder, wo nicht in String wird als NULL gehalten werden. Wenn Sie Feld von Ihrem Objekt entfernt haben, werden ältere Versionen dieses Feld halten, wie Allways-NULL, die zu Fehlverhalten führen können, wenn ältere Versionen auf Daten in diesem Bereich verlassen (sowieso Sie haben es für etwas geschaffen, nicht nur zum Spaß :-))

Am wenigsten offensichtlich - Sie manchmal die Idee, die Sie in einem Feld von Bedeutung setzen verändern. Zum Beispiel, wenn Sie sind 12 Jahre alt you „Fahrrad“ unter „Fahrrad“ bedeuten, aber wenn Sie 18 sind meinen Sie „Motorrad“ - wenn Ihre Freunde Sie einladen, „Radtour über Stadt“ und Sie werden die einzige sein, kam auf dem Fahrrad, wird undestand Sie, wie wichtig es gleiche Bedeutung über Felder zu halten ist: -)

Zum einen um Ihre Frage zu beantworten, wenn wir in unserer Klasse nicht SerialVersionUID deklarieren, erzeugt Java Runtime es für uns, aber das Verfahren ist empfindlich für viele Klasse Metadaten wie die Anzahl der Felder, die Art der Felder, Zugriffsmodifikator von Feldern , Schnittstelle nach Klasse usw. implementiert Daher wird empfohlen, es selbst zu erklären und Eclipse Sie über das gleiche warnt.

Serialisierung: Wir arbeiten oft mit wichtigen Objekte, deren Zustand (Daten in den Variablen des Objekts) ist so wichtig, dass wir sie nicht durch Strom / Systemausfälle zu verlieren riskieren (oder), Netzwerk-Ausfälle bei den Objektstatus zu anderen Maschine zu senden. Die Lösung für dieses Problem ist „Persistence“ genannt, was einfach bedeutet, persistierende (Halte / Speichern), um die Daten. Serialisierung ist eine der vielen anderen Möglichkeiten, um Ausdauer zu erreichen (von Daten auf der Festplatte / Speicher zu speichern). Wenn der Zustand des Objekts zu speichern, ist es wichtig, eine Identität für das Objekt, zu schaffen, um die Lage sein, wieder lesen es richtig (de-Serialisierung). Diese eindeutige Identifikation ist ID ist SerialVersionUID.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top