serialVersionUID

Alles zu NetBeans als RCP-Platform

Moderator: wegus

Antworten
Benutzeravatar
stophi
Beiträge: 150
Registriert: 02.03.2007, 07:32
Wohnort: München
Kontaktdaten:

serialVersionUID

Beitrag von stophi » 19.04.2007, 16:14

Wozu braucht man eine serialVersionUID?
Irgendwie bekommt man wohl Probleme bei Deserialisieren, wenn man es nicht setzt. Da hab ich einfach mal irgendeine Nummer gewählt, dann kam eine InvalidClassException.
Was für eine Nummer muss man da wählen?
Kann die nicht mit irgendwelchen anderen, schon bestehenden Nummern kolidieren?

Also ich hab keine Ahnung, was man machen muss, damit es anständig funktioniert.

Benutzeravatar
recJake
Beiträge: 669
Registriert: 19.07.2006, 11:50
Wohnort: IDEs

Beitrag von recJake » 19.04.2007, 16:30

Hier ist das einigermaßen leidlich gut erklärt. :)
J..e
Willst Du coden, so code. Willst Du nutzen, so nutze. Willst Du beides, lass es!

Benutzeravatar
stophi
Beiträge: 150
Registriert: 02.03.2007, 07:32
Wohnort: München
Kontaktdaten:

Beitrag von stophi » 19.04.2007, 17:19

Ja, danke. Das hilft mir aber leider nicht bei meinem Problem.
Also ich habe ein NetBeans-Modul, das persistente Komponenten haben soll. Ein Modul zum editieren von Html-Dateien. Die Dateien, die beim Schließen im Editor geöffnet waren, sollen beim Neustart wieder angezeigt werden.

Beim Schließen der Testumgebung kam immer eine Warnung, dass das Deserialisieren nicht geklappt hat und der Hinweis, dass ich die serialVersionUID für "HtmlEditorSupport.HtmlEnv" (so heißt die Klasse) setzen soll.
Beim Neustart der Testumgebung hat er die Komponenten, die er anzeigen soll, nie angezeigt, denn er hat es ja nicht deserialisieren können.
Vielleicht hat das aber auch nix miteinander zu tun.

Jetzt verstehe ich immer noch nicht, warum man die serialVersionUID von Hand setzen muss und auf welchen Wert man sie setzen muss. "1L" hat nicht geklappt und dieses Tool "serialver" funktioniert bei mir nicht, er findet die Klasse nicht?! Hab auch schon alle möglichen Konstellationen ausprobiert, er findet prinzipiell keine Klasse, die man ihm reinfüttert. :?

Benutzeravatar
recJake
Beiträge: 669
Registriert: 19.07.2006, 11:50
Wohnort: IDEs

Beitrag von recJake » 20.04.2007, 08:44

Ok, das mit "serialver" ist schon ein wenig schwierig, weil die Doku dazu echt Müll ist. Also Schritt für Schritt:

1. Vorraussetzung
Die zu serialisierende Klasse muß das Interface java.io.Serializable implementieren

2. Anwendung von serialver
a) Bei serialver muß zwingend ein Klassenpfad angegeben werden und zwar der vollständige. Das heißt, wenn die Klasse von einer anderen erbt oder Objekte eines Typs hat, der nicht zum JDK gehört und die nicht transient sind, dann muß im Klassenpfad auch ein Eintrag vorhanden sein, der diese Klassen referenziert. Bei NetBeans-Modulen also eine ganz Menge davon.

b) Der Separator für die Classpatheinträge ist nicht, wie in allen anderen JDK-Tools üblich, das Semikolon, sondern der Doppelpunkt. Das ist besonders für Windowsnutzer wichtig, weil sie nämlich, wenn ein Eintrag der cp-Angaben einen absoluten Pfad enthält, diesen Eintrag in Anführungszeichen setzen müssen.
Mal ein Beispiel:

Code: Alles auswählen

serialver -classpath C:\Programme\blabla IrgendeineKlasse
So wie es jetzt geschrieben ist, würde "serialver" folgende CP-Einträge finden:
i. C
ii. \Programme\blabla


Das wäre natürlich falsch und die Klasse würde nicht gefunden, also muß man schreiben:

Code: Alles auswählen

serialver -classpath "C:\Programme\blabla" IrgendeineKlasse
c) Der CP-Eintrag in dem sich Deine Klasse befindet, muß aber vor dem ersten package-Bestandteil aufhören.
Also angenommen man hat eine Klasse: de.nbforum.Test und die Klasse liegt in C:\Module\NbForum\build\classes\de\nbforum, dann muß der serialver-Aufruf lauten:

Code: Alles auswählen

serialver -classpath "C:\Module\NbForum\build\classes" de.nbforum.Test
(Achtung, der letzte Teil eines CP-Eintrages darf kein Slash oder Backslash sein)

d) Serialver kann nur auf kompilierten Klassen aufgerufen werden. Es funktioniert nicht auf den Sourcen.

Hinweis: Eine serialVersionUID ist immer negativ. Frag mich nicht warum, ich habe keine Ahnung.

3. Nutzen der serialVersionUID
a) Der von serialver erzeugte String kann und muß genauso wie er angezeigt wird, in die Klasse kopiert werden. Die Klasse darf sich danach auch nicht mehr ändern, sonst ist die Nummer ungültig und vor der Änderung gespeicherte Objekte können nicht mehr gelesen werden.
Beispiel:

Code: Alles auswählen

public class Test {
  static final long serialVersionUID = -4726593233666458481L;
  public int testInt = 0;
}
Ich serialisiere jetzt ein Objekt dieser Klasse. Alles super!
Jetzt füge ich der Klasse eine Methode hinzu.
Wenn ich jetzt versuche mein Objekt zu deserialisieren bekomme ich einen Fehler weil das gespeicherte Objekt nicht mehr zu der Klasse passt
b) Die zu (de)serialisierende Klasse sollte die Methoden writeObject() und readObject() implementieren, muß aber nicht. Es gibt auch andere Wege - hängt natürlich immer von der Implementierung ab.

Ich hoffe, das hilft Dir, um überhaupt erstmal eine UID zu erzeugen. :)

Ich muß mal schauen (also nach dem Urlaub), irgendwo, habe ich noch so ein halbfertiges Modul für NetBeans, mit dem man für Klassen serialVersionUIDs erzeugen kann.
J..e
Willst Du coden, so code. Willst Du nutzen, so nutze. Willst Du beides, lass es!

Benutzeravatar
vanGorn
Beiträge: 191
Registriert: 24.07.2006, 12:47

Beitrag von vanGorn » 21.04.2007, 18:52

In den apidocs steht bei serialisierbaren Klassen ja meistens, dass sich die Serialisierung in Zukunft vorraussichtlich ändern wird. Ich nehme mal an, dass damit eventuell der Umstieg auf die XML-Serialisierung gemeint ist. Ab welcher Java-Version darf man denn wohl damit rechnen?

Benutzeravatar
stophi
Beiträge: 150
Registriert: 02.03.2007, 07:32
Wohnort: München
Kontaktdaten:

Beitrag von stophi » 12.07.2007, 16:31

recJake hat geschrieben: Ich hoffe, das hilft Dir, um überhaupt erstmal eine UID zu erzeugen. :)
Leider nicht. Er findet die Klassen aus den anderen Modulen nicht. Und wenn ich versuche, den Classpath zusammen zu fügen, dann meint er, dass er den Classpath nicht parsen kann.

Also ich mache das momentan so:

Code: Alles auswählen

set SUITE_ROOT=C:\PFAD\ZU\MEINER\SUITE
C:\Programme\Java\jdk1.6.0\bin\serialver -classpath "%SUITE_ROOT%\ModulABC\build\classes":"%SUITE_ROOT%\ModulXYZ\build\classes" myorg.myapp.moduleabc.MyClass
Müsste doch so stimmen, oder? Aber irgendwie bekommt er es nicht auf die Reihe, den Classpath der Module miteinander zu verbinden.

Wenn ich nur den Pfad zu einem Modul angebe, dann "funktioniert" es, er löst aber eine Exception aus, weil er eine Klasse nicht gefunden hat. Was ja auch klar ist, weil sie in einem anderen Modul liegt. :roll:

Also ich bin jetzt kurz davor aufzugeben. Werde das ganze wohl mit XML Persistenz machen. Serialisierung ist doof. :P

Antworten