OVH Cloud OVH Cloud

serialization

10 réponses
Avatar
Kupee
Salut j'ai quelque problèmes avec la sérialisation en java.
Déjà d'interopérabilité : j'ai une classe qui implémente
java.io.Serializable je lui ai collé un serialVersionUID
private static final long serialVersionUID = 6112863038402523860L;
calculé par l'executable livré avec la jvm.
J'ai un petit serveur qui sérialise cette classe et un client qui la recoit.
Et il y a un conflit de serialVersionUID : le serveur n'envoit pas le
bon ...
Pourtant lorsque je suis en debug dans mon programme il semble correct
et je suis sur que les .class sont les mêmes des 2 cotés ...
Une idée de la raison pour laquelle il pourrait faire ca ?

Sinon une question sur externalizable :
ca permet de controler la sérialisation en implémentant les méthodes
public void writeExternal(ObjectOutput out)
throws IOException
et
public void readExternal(ObjectInput in)
throws IOException,
ClassNotFoundException

Mais quelle différence par rapport aux méthodes
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
que l'on peut implémenter avec serializable ?

Merci

10 réponses

Avatar
Kupee
Hervé AGNOUX wrote:
J'ai un petit serveur qui sérialise cette classe et un client qui la
recoit. Et il y a un conflit de serialVersionUID : le serveur n'envoit pas
le bon ...



Il y a forcément un bémol chez toi quelque part... As-tu essayé en local ?
Que donne le serialver ? De quelle version date les objets sérialisés que
tu échanges ? Etc...


Je les échange via un socket donc il n'y a pas d'histoire comme quoi ca
aurait été sérialisé avec une version puis ca aurait changé parce que
mes classes sont modifiées. J'ai même essayé avec le même jar (le client
et le serveur dans le même jar, lancés au même endroit ...


Avatar
Hervé AGNOUX
Kupee wrote:

J'ai un petit serveur qui sérialise cette classe et un client qui la
recoit. Et il y a un conflit de serialVersionUID : le serveur n'envoit pas
le bon ...


Il y a forcément un bémol chez toi quelque part... As-tu essayé en local ?
Que donne le serialver ? De quelle version date les objets sérialisés que
tu échanges ? Etc...


Pourtant lorsque je suis en debug dans mon programme il semble correct
et je suis sur que les .class sont les mêmes des 2 cotés ...
Une idée de la raison pour laquelle il pourrait faire ca ?

Sinon une question sur externalizable :
ca permet de controler la sérialisation en implémentant les méthodes
public void writeExternal(ObjectOutput out)
throws IOException
et
public void readExternal(ObjectInput in)
throws IOException,
ClassNotFoundException

Mais quelle différence par rapport aux méthodes
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
que l'on peut implémenter avec serializable ?



Je ne sais pas. J'ai toujours utilisé serializable car cela fonctionne
parfaitement. Donc je ne suis pas allé plus loin !



--
Hervé AGNOUX
http://www.diaam-informatique.com

Avatar
Fabien Bergeret
Kupee wrote:
Salut j'ai quelque problèmes avec la sérialisation en java.
Déjà d'interopérabilité : j'ai une classe qui implémente
java.io.Serializable je lui ai collé un serialVersionUID
private static final long serialVersionUID = 6112863038402523860L;
calculé par l'executable livré avec la jvm.
J'ai un petit serveur qui sérialise cette classe et un client qui la
recoit.
Et il y a un conflit de serialVersionUID : le serveur n'envoit pas le
bon ...
Pourtant lorsque je suis en debug dans mon programme il semble correct
et je suis sur que les .class sont les mêmes des 2 cotés ...
Une idée de la raison pour laquelle il pourrait faire ca ?

Sinon une question sur externalizable :
ca permet de controler la sérialisation en implémentant les méthodes
public void writeExternal(ObjectOutput out)
throws IOException
et
public void readExternal(ObjectInput in)
throws IOException,
ClassNotFoundException

Mais quelle différence par rapport aux méthodes
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
que l'on peut implémenter avec serializable ?

Merci
Pourquoi as tu créé un serialVersionUID ?

Que ce passe t'il si tu le supprimes ?
Es tu sûr que les classes que tu charges sont bien dans le même jar ? Tu
peux t'en assurer en lisant l'article suivant (in English) :
http://www-128.ibm.com/developerworks/websphere/techjournal/0406_brown/0406_brown.html?ca=dnp-326

Pour 'Externalizable', j'ai l'impression que c'est pour créer ton propre
format de serialization, indépendant de la seralisation de Sun.

Avatar
Kupee
Fabien Bergeret wrote:
Pourquoi as tu créé un serialVersionUID ?


Pour éviter les problèmes si j'ai un client et un serveur qui n'ont pas
été compilés avec exactement les mêmes classes.

Que ce passe t'il si tu le supprimes ?


Même problème, il fait une exception InvalidClassException en disant que
sur le stream il trouve un serialVersionUID qui n'est pas celui qu'il
attend.

Ce qui est bizarre c'est que coté serveur je fait un System.out du
serialVersionUID et c'est bien ce que j'ai mis dans ma classe
(6112863038402523860), et coté client il me dit ca
local class incompatible: stream classdesc serialVersionUID =
6112862711979176660, local class serialVersionUID = 6112863038402523860

En bref le serialVersionUID qui est passé sur le stream n'est pas celui
que j'ai fixé dans ma classe ...

Es tu sûr que les classes que tu charges sont bien dans le même jar ? Tu
peux t'en assurer en lisant l'article suivant (in English) :
http://www-128.ibm.com/developerworks/websphere/techjournal/0406_brown/0406_brown.html?ca=dnp-326


Je connaissais pas l'astuce, c'est bien pratique merci. Mais oui c'est
bien le même jar ...

Pour 'Externalizable', j'ai l'impression que c'est pour créer ton propre
format de serialization, indépendant de la seralisation de Sun.


Oui, le seul truc bizarre c'est que avec Serializable on peut faire un
truc a peu près pareil et j'ai du mal a suivre la différence ...

Avatar
Hervé AGNOUX
Kupee wrote:


Je les échange via un socket donc il n'y a pas d'histoire comme quoi ca
aurait été sérialisé avec une version puis ca aurait changé parce que
mes classes sont modifiées. J'ai même essayé avec le même jar (le client
et le serveur dans le même jar, lancés au même endroit ...


Même jar, même serveur, même endroit, même classe, c'est quasi-impossible.

Allons-y pour les vieilles méthodes ! Peux-tu tracer le nom de la classe de
l'objet juste avant la serialization, le message d'erreur, le nom de la
classe attendue, et ton classpath ?


--
Hervé AGNOUX
http://www.diaam-informatique.com

Avatar
Fabien Bergeret
Kupee wrote:
Fabien Bergeret wrote:

Pourquoi as tu créé un serialVersionUID ?



Pour éviter les problèmes si j'ai un client et un serveur qui n'ont pas
été compilés avec exactement les mêmes classes.

Que ce passe t'il si tu le supprimes ?



Même problème, il fait une exception InvalidClassException en disant que
sur le stream il trouve un serialVersionUID qui n'est pas celui qu'il
attend.

Ce qui est bizarre c'est que coté serveur je fait un System.out du
serialVersionUID et c'est bien ce que j'ai mis dans ma classe
(6112863038402523860), et coté client il me dit ca
local class incompatible: stream classdesc serialVersionUID =
6112862711979176660, local class serialVersionUID = 6112863038402523860

En bref le serialVersionUID qui est passé sur le stream n'est pas celui
que j'ai fixé dans ma classe ...

Es tu sûr que les classes que tu charges sont bien dans le même jar ?
Tu peux t'en assurer en lisant l'article suivant (in English) :
http://www-128.ibm.com/developerworks/websphere/techjournal/0406_brown/0406_brown.html?ca=dnp-326




Je connaissais pas l'astuce, c'est bien pratique merci. Mais oui c'est
bien le même jar ...

Pour 'Externalizable', j'ai l'impression que c'est pour créer ton
propre format de serialization, indépendant de la seralisation de Sun.



Oui, le seul truc bizarre c'est que avec Serializable on peut faire un
truc a peu près pareil et j'ai du mal a suivre la différence ...
Une autre piste : si ton client est une applet, peut être une ancienne

version est elle restée dans le cache.
Tu peux vider le cache par le panneau de configuration du plugin Java


Avatar
Kupee
Fabien Bergeret wrote:
Une autre piste : si ton client est une applet, peut être une ancienne
version est elle restée dans le cache.
Tu peux vider le cache par le panneau de configuration du plugin Java


Eh non c'est un client lourd ...

Avatar
Olivier Thomann
Fabien Bergeret wrote:
Eh non c'est un client lourd ...
Est-il possible de tester nous même ce qui se passe?

--
Olivier

Avatar
Kupee
Olivier Thomann wrote:
Fabien Bergeret wrote:
Eh non c'est un client lourd ...


Est-il possible de tester nous même ce qui se passe?


Malheureusement non désolé je ne peux pas le distribuer.
C'est sur qu'il doit y avoir un problème vraiment idiot mais je le
trouve pas.
Finalement j'ai trouvé une solution pas si mal, avoir ma propre fonction
de sérialisation genre serialize(ObjectOutput out) dans mes objets
et une fonction static qui me réinstantie l'objet a partir de
ObjectInput, mes objets étant tous liés je crois que c'est finalement
mieux, ca m'évite de retransférer la totalité a chaque fois, car le
client garde une partie en cache :)


Avatar
Fabien Bergeret
Kupee wrote:
Olivier Thomann wrote:

Fabien Bergeret wrote:
Eh non c'est un client lourd ...



Est-il possible de tester nous même ce qui se passe?



Malheureusement non désolé je ne peux pas le distribuer.
C'est sur qu'il doit y avoir un problème vraiment idiot mais je le
trouve pas.
Finalement j'ai trouvé une solution pas si mal, avoir ma propre fonction
de sérialisation genre serialize(ObjectOutput out) dans mes objets
et une fonction static qui me réinstantie l'objet a partir de
ObjectInput, mes objets étant tous liés je crois que c'est finalement
mieux, ca m'évite de retransférer la totalité a chaque fois, car le
client garde une partie en cache :)
L'appli sur laquelle je bosse comporte une applet, qui dialogue avec le

serveur en transmettant des objets serialises compresses.
Pour éviter le problème des classes incompatibles, qui peuvent parfois
être dues aux classes Java elles-mêmes, qui peuvent être différentes sur
l'applet et sur le serveur d'application (JRE 1.3.1 sur le client et
1.4.2 sur le serveur par exemple), les objets sérialisés qui transitent
ne sont que des objets que l'on maîtrise entièrement, c'est à dire qui
ne sont composés que de types primaires, de wrapper (Integer, Double,
...), de String ou d'autres objets entierement maitrises. Le but etant
de ne pas transmettre de classes du JRE autres que wrappers et String
par serialisation ...