Question

En Java, les champs statiques et transitoires ne sont pas sérialisés.Cependant, j'ai découvert que l'initialisation des champs statiques entraînait la modification du SerialVersionUID généré.Par exemple, static int MYINT = 3; entraîne la modification du SerialVersionUID.Dans cet exemple, cela est logique car différentes versions de la classe obtiendraient des valeurs initiales différentes.Pourquoi toute initialisation modifie-t-elle le SerialVersionUID ?Par exemple, static String MYSTRING = System.getProperty("foo"); entraîne également la modification du SerialVersionUID.

Pour être précis, ma question est de savoir pourquoi l'initialisation avec une méthode entraîne la modification du SerialVersionUID.Le problème que j'ai rencontré est que j'ai ajouté un nouveau champ statique initialisé avec une valeur de propriété système (getProperty).Ce changement a provoqué une exception de sérialisation lors d'un appel distant.

Était-ce utile?

La solution

Vous pouvez trouver des informations à ce sujet dans le bogue 4365406 et dans le algorithme pour l'informatique SerialVersionUID.Fondamentalement, lorsque vous modifiez l'initialisation de votre static membre avec System.getProperty(), le compilateur introduit un nouveau static propriété de votre classe faisant référence au System classe (je suppose que le System n'était pas référencée auparavant dans votre classe), et comme cette propriété introduite par le compilateur n'est pas privée, elle participe à la serialVersionUID calcul.

Moralité:utilisez toujours explicite serialVersionUID, vous économiserez quelques cycles CPU et quelques maux de tête :)

Autres conseils

Le SerialVersionUID automatique est calculé en fonction des membres d’une classe.Ceux-ci peuvent être affichés pour un fichier de classe à l'aide de l'outil javap du Sun JDK.

Dans le cas mentionné dans la question, le membre ajouté/supprimé est l'initialiseur statique.Cela apparaît comme ()V dans les fichiers de classe.Le contenu de la méthode peut être désassemblé en utilisant javap -c.Vous devriez être en mesure de distinguer l'appel System.getProperty("foo") et l'affectation à MYSTRING.Cependant, une affectation avec une chaîne littérale (ou toute constante de compilation telle que définie par la spécification du langage Java) est prise en charge directement par le fichier de classe, éliminant ainsi le besoin d'un initialiseur statique.

Un cas courant de code ciblant J2SE 1.4 (utilisez -source 1.4 -target 1.4) ou une version antérieure est celui des champs statiques des anciennes instances de classe qui apparaissent comme des littéraux de classe dans le code source (MyClass.class).L'instance de classe est recherchée à la demande avec Class.forName et stockée dans un champ statique.C'est ce champ statique qui perturbe le serialVersionUID.Depuis J2SE 5.0, une variante de l'opcode ldc prend directement en charge les littéraux de classe, supprimant ainsi le besoin du champ synthétique.Encore une fois, tout cela peut être affiché avec javap -c.

Si j'ai lu correctement les spécifications, l'automatique serialVersionUID ne devrait pas changer si vous modifiez la valeur d'un champ statique ou transitoire.Jeter un coup d'œil à Chapitre 5.6 de la Spéc.

Cependant, si vous y réfléchissez un peu, vous commencez par sérialiser un objet qui a static int MYINT = 3, lorsque vous désérialisez ensuite la classe, vous espérez récupérer le même objet, c'est-à-dire avec MYINT = 3.Ainsi, si vous modifiez l'initialisation statique, vous vous attendez à ce que le serialVersionUID changer car vous ne pouvez pas récupérer le même objet.

De toute façon, conservez-le dans toutes vos classes sérialisables et vous pourrez contrôler le serialVersionUID:

private static final long serialVersionUID = 7526472295622776147L;

J'ai mis à jour la question pour être plus claire.Je comprends pourquoi l'initialisation avec un littéral change le serialVersionUID mais pas pourquoi l'initialisation dynamique le change.Si vous initialisez avec une méthode, la valeur, bien entendu, peut toujours être différente.

Réglage du serialVersionUID explicitement, cela convient dans une version ultérieure de la classe uniquement si vous êtes sûr qu'il s'agit d'un changement sûr.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top