Ich habe hier ein Problem mit einem serialisierten PublicKey, den ich in
meinem Anwendungsjar gespeichert habe und im Programm einlese.
Erstellt wurde der PublicKey unter JDK 1.4.2 und damit klappt das einlesen
natürlich problemlos.
Unter MacOS X (=1.4.1 von Apple) bekomme ich beim Einlesen des Key allerdings
eine InvalidClassException:
java.io.InvalidClassException: com.sun.net.ssl.internal.ssl.JSA_RSAPublicKey;
local class incompatible: stream classdesc serialVersionUID = -
4603577243802113781, local class serialVersionUID = -8509221176441256992
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:459)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1521)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1435)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1626)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1274)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
OK, soweit akzeptiert. Gibt es da nun aber eine Möglichkeit weiter unter
1.4.2 zu entwickeln und den PublicKey trotzdem unter 1.4.1 einlesen zu
können?
Der PublicKey sollte dabei unangetastet bleiben.
Gruß
Andreas
> OK, soweit akzeptiert. Gibt es da nun aber eine Möglichkeit weiter
> unter 1.4.2 zu entwickeln und den PublicKey trotzdem unter 1.4.1
> einlesen zu können?
>
> Der PublicKey sollte dabei unangetastet bleiben.
Statt Serialisierung für sowas zu "missbrauchen" könntest du ja den
Schlüssel in einem "normalen" Format speichern. Du würdest ja
wahrscheinlich auch nicht Bilder oder XML-Dokuemente als serialisierte
Java-Objekte speichern, oder?
Mit Key.getEncoded() kriegst du ein byte-Array, in dem der Schlüssel in
einem "üblichen" Format kodiert ist, bei privaten RSA-Schlüsseln wird es
wohl PCKS#8 sein. Das Array kannst du speichern, später einlesen und mit
einer KeySpec-Implementierung und einem KeyFactory daraus einen Schlüssel
machen.
Gruß, Tor
Andreas Bacher wrote:
> java.io.InvalidClassException: com.sun.net.ssl.internal.ssl.JSA_RSAPublicKey;
> local class incompatible: stream classdesc serialVersionUID = -
> 4603577243802113781, local class serialVersionUID = -8509221176441256992
Solange die Objekte noch kompatibel sind, kannst du als Workaround die
serialVersionUID in der Klasse konstant setzen:
public class Sowieso {
public static final long serialVersionUID=-5708462929351502788L;
}
Wer natürlich Klassen aus einem com.sun Package serialisiert und sich
dann wundert, dass er sie nicht mehr deserialisieren kann, dem kann man
zu dem Zeitpunkt nicht mehr helfen. Du wirst die Serialisierung durch
etwas anderes ersetzen müssen (XML, String, BLOB, ...).
Andreas Bacher wrote:
> Hallo dclj!
>
> Ich habe hier ein Problem mit einem serialisierten PublicKey, den ich in
> meinem Anwendungsjar gespeichert habe und im Programm einlese.
> Erstellt wurde der PublicKey unter JDK 1.4.2 und damit klappt das einlesen
> natürlich problemlos.
>
> Unter MacOS X (=1.4.1 von Apple) bekomme ich beim Einlesen des Key allerdings
> eine InvalidClassException:
>
> java.io.InvalidClassException: com.sun.net.ssl.internal.ssl.JSA_RSAPublicKey;
> local class incompatible: stream classdesc serialVersionUID = -
> ...
> OK, soweit akzeptiert. Gibt es da nun aber eine Möglichkeit weiter unter
> 1.4.2 zu entwickeln und den PublicKey trotzdem unter 1.4.1 einlesen zu
> können?
>
> Der PublicKey sollte dabei unangetastet bleiben.
>
> Gruß
> Andreas
abgesehen davon, dass es genügend Standardformate gibt um Schlüssel zu
speichern hast Du vermutlich eines der Standardversäumnisse bei der
Serialisierung begangen:
Deine Klasse definiert kein "public static final long serialVersionUID"!
Ist in einer als serialisierbar markierten Klasse dieses Member nicht
enthalten, so berechnet die VM den Wert. Da aber keine allgemein gültige
Formel dafür definiert ist, berechnet das jede VM anders. Somit kommt es
dann zu den Exceptions wenn ein Objekt aus einer VM serialisiert und in
eine andere VM deserialisiert wird.
Ullrich.
> Mit Key.getEncoded() kriegst du ein byte-Array, in dem der Schl ssel in
> einem " blichen" Format kodiert ist, bei privaten RSA-Schl sseln wird es
> wohl PCKS#8 sein. Das Array kannst du speichern, sp„ter einlesen und mit
> einer KeySpec-Implementierung und einem KeyFactory daraus einen Schl ssel
> machen.
Hat mit einer X509EncodedKeySpec und der KeyFactory jetzt prima geklappt.
Danke für den nützlichen Hinweis.
Zugegeben, die Serialisierung hab ich in der Tat bisher nur mißbraucht. Man
sucht sich halt zunächst die einfachste Lösung, bis man draufkommt das es zu
einfach war ;-)
Gruß
Andreas
> abgesehen davon, dass es gen gend Standardformate gibt um Schl ssel zu
> speichern hast Du vermutlich eines der Standardvers„umnisse bei der
> Serialisierung begangen:
Yo scheint so ;-)
> Deine Klasse definiert kein "public static final long serialVersionUID"!
> Ist in einer als serialisierbar markierten Klasse dieses Member nicht
> enthalten, so berechnet die VM den Wert. Da aber keine allgemein g ltige
> Formel daf r definiert ist, berechnet das jede VM anders. Somit kommt es
> dann zu den Exceptions wenn ein Objekt aus einer VM serialisiert und in
> eine andere VM deserialisiert wird.
Danke für den Tip. Ich hab's in diesem Fall mit KeySpec und KeyFactory
gelöst, aber die Sache mit der serialVersionUID wußte ich so noch nicht!
Gruß
Andreas
> abgesehen davon, dass es genügend Standardformate gibt um Schlüssel zu
> speichern hast Du vermutlich eines der Standardversäumnisse bei der
> Serialisierung begangen:
> Deine Klasse definiert kein "public static final long
> serialVersionUID"!
Es war ja nicht seine Klasse, sondern eine Klasse aus der VM. Dagegen kann
er wahrscheinlich wenig machen.
> Ist in einer als serialisierbar markierten Klasse
> dieses Member nicht enthalten, so berechnet die VM den Wert. Da aber
> keine allgemein gültige Formel dafür definiert ist, berechnet das jede
> VM anders.
Das stimmt doch so nicht, oder? Ich dachte, dass jede Klasse eine
Seriennummer haben muss und dass diese wenn nicht explizit angegeben schon
von dem Compiler als Zufallszahl vergeben wird. Wenn es tatsächlich die
gleiche Class-Datei ist, wirst du also mit unterschiedlichen VMs keine
Probleme haben. Die Klassen aus den verschiedenen VM-Versionen werden wohl
aber unterschiedlich kompiliert worden sein.
Gruß, Tor
> abgesehen davon, dass es genügend Standardformate gibt um Schlüssel zu
> speichern hast Du vermutlich eines der Standardversäumnisse bei der
> Serialisierung begangen:
> Deine Klasse definiert kein "public static final long serialVersionUID"!
> Ist in einer als serialisierbar markierten Klasse dieses Member nicht
> enthalten, so berechnet die VM den Wert. Da aber keine allgemein gültige
> Formel dafür definiert ist, berechnet das jede VM anders.
In der Serialisierungs-Spezifikation ist eine
Formel definiert. Der Wert hängt allerdings auch
z.B. von den vorhandenen Methoden ab ...
Paul
> Ullrich Pollaehne <u.poll...@web.de> wrote [...]
>
> > Ist in einer als serialisierbar markierten Klasse
> > dieses Member [serialVersionUID] nicht enthalten, so berechnet die VM
> > den Wert. Da aber keine allgemein gültige Formel dafür definiert ist,
> > berechnet das jede VM anders.
>
> Das stimmt doch so nicht, oder?
Nein.
> Ich dachte, dass jede Klasse eine
> Seriennummer haben muss und dass diese wenn nicht explizit angegeben schon
> von dem Compiler als Zufallszahl vergeben wird.
Das stimmt aber auch nicht.
http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html#wp3169
Es macht die VM (bzw. das Serialisierungs-System), nicht
der Compiler. Wobei man auch auf
http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html#wp5440
hinweisen sollte - das kommt dann deiner Annahme einer
Compiler-Zufallszahl schon recht nah.
Paul
> Das stimmt aber auch nicht.
"Ich dachte" ja auch nur. Sicher war ich nicht :)
> http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html
> #wp3169
>
> Es macht die VM (bzw. das Serialisierungs-System), nicht
> der Compiler. Wobei man auch auf
>
> http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html
> #wp5440
>
> hinweisen sollte - das kommt dann deiner Annahme einer
> Compiler-Zufallszahl schon recht nah.
Das kann schon sein. Ich habe nicht allzu viel mit Serialisierung
gemacht, es ist mir aber öfter aufgefallen, dass die serialVersionUID
sich änder kann, wenn die Klasse neu kompiliert wird, ohne dass ich
irgendwelche für die Serialisierung relevante Felder geändert habe. Aber
wenn nun auch andere Methoden, Konstruktoren und innere Klassen mit in
der Berechnung einfließen wird es wohl daran liegen.
Gruß, Tor
Schöne Doku, aber Papier (bzw. Elektronen) sind geduldig. ;-)
Die Realität sieht oft anders aus.
Ullrich.
Klar, Bugs gibt es immer.
Hast du hier einen konkreten Fall, wo es
zu beobachten ist, dass das nicht klappt?
Paul
Der beschriebene, mit dem der ganze Thread anfing?
Ausserdem aus eigener Erfahrung: MS (jaja, ich weiss) <-> SUN.