Comment fonctionne la sérialisation Java et quand doit-elle être utilisée à la place d’une autre technique de persistance?

Ces derniers temps, je me suis efforcé d’approfondir mes connaissances et de tester généralement la sérialisation de Java pour les projets professionnels et personnels, et je dois dire que plus j’en connais, moins je l’aime. Cela peut être causé par la désinformation, c’est pourquoi je vous demande ces deux choses:

1: Au niveau des octets, comment la sérialisation sait-elle faire correspondre les valeurs sérialisées à une classe?

Un de mes problèmes ici est que j’ai fait un petit test avec ArrayList contenant les valeurs “un”, “deux”, “trois”. Après la sérialisation, le tableau d’octets prenait 78 octets, ce qui semble énormément pour une si faible quantité d’informations (19 + 3 + 3 + 4 octets). Certes, il y aura forcément des frais généraux, mais ceci mène à ma deuxième question:

2: La sérialisation peut-elle être considérée comme une bonne méthode pour la persistance d’objects? Maintenant, évidemment, si j’utilisais un format XML fait maison, les données de persistance ressembleraient à ceci

    One Two Three   

qui, comme XML en général, est un peu gonflé et prend 138 octets (sans espaces, c’est-à-dire). La même chose en JSON pourrait être

 { "java.util.ArrayList": { "elementData": [ "one", "two", "three" ] } } 

ce qui est déjà 75 octets donc légèrement plus petit que la sérialisation de Java. Avec ces formats textuels, il est bien entendu évident qu’il doit exister un moyen de représenter vos données de base sous forme de texte, de chiffres ou de toute combinaison des deux.

Donc, pour récapituler, comment fonctionne la sérialisation au niveau octet / bit, quand elle devrait être utilisée et quand elle ne devrait pas être utilisée, et quels sont les avantages réels de la sérialisation en plus du fait qu’elle est standard en Java?

Je voudrais personnellement essayer d’éviter la sérialisation “intégrée” de Java:

  • Ce n’est pas portable sur d’autres plateformes
  • Ce n’est pas extrêmement efficace
  • C’est fragile – il est parfois difficile de gérer plusieurs versions d’une classe. Même les compilateurs modifiés peuvent interrompre la sérialisation à moins que vous ne soyez prudent.

Pour plus d’informations sur la signification des octets réels, reportez-vous à la spécification de sérialisation des objects Java .

Il existe différentes alternatives, telles que:

  • XML et JSON, comme vous l’avez montré (diverses variantes de XML, bien sûr)
  • YAML
  • Facebook’s Thrift (RPC ainsi que la sérialisation)
  • Tampons de protocole Google
  • Hesse (services Web ainsi que la sérialisation)
  • Apache Avro
  • Votre propre format personnalisé

(Avertissement: je travaille pour Google et je construis un port de protocole tampon en C # pour mon projet à 20%. Je pense donc clairement que c’est un bon élément de technologie 🙂

Les formats multiplates-formes sont presque toujours plus ressortingctifs que les formats spécifiques à une plate-forme pour des raisons évidentes – Les tampons de protocole ont un ensemble assez limité de types natifs, par exemple – mais l’interopérabilité peut être incroyablement utile. Vous devez également prendre en compte l’impact de la gestion des versions, avec la compatibilité ascendante, ascendante, etc. Les formats de texte sont généralement modifiables à la main, mais ont tendance à être moins efficaces dans l’espace et dans le temps.

Fondamentalement, vous devez examiner attentivement vos exigences.

Le principal avantage de la sérialisation est qu’elle est extrêmement facile à utiliser, relativement rapide et qu’elle préserve les maillages réels des objects Java.

Mais vous devez comprendre que ce n’est pas vraiment destiné à stocker des données, mais principalement comme moyen pour différentes instances de JVM de communiquer sur un réseau en utilisant le protocole RMI.

Pour plus d’informations sur le format de fichier et sur la grammaire utilisée pour les objects sérialisés, reportez-vous au Java Stream Serialization Stream Protocol .

Personnellement, je pense que la sérialisation intégrée est acceptable pour la persistance de données de courte durée (par exemple, le stockage de l’état d’un object de session entre deux requêtes http), ce qui n’est pas pertinent en dehors de votre application.

Pour les données dont la durée de vie est plus longue ou qui devraient être utilisées en dehors de votre application, je persistais soit dans une firebase database, soit du moins en utilisant un format plus couramment utilisé …

Comment fonctionne la sérialisation intégrée de Java?

Chaque fois que nous voulons sérialiser un object, nous implémentons l’interface java.io.Serializable. L’interface qui n’a aucune méthode à implémenter, même si nous l’implémentons pour indiquer quelque chose au compilateur ou à la JVM (connue sous le nom de Marker Interface ). Ainsi, si la machine virtuelle Java constate qu’une classe est sérialisable, elle effectue certaines opérations de prétraitement sur ces classes. L’opération est, il ajoute les deux exemples de méthodes suivants.

 private void writeObject(java.io.ObjectOutputStream stream) throws IOException { stream.writeObject(name); // object property stream.writeObject(address); // object property } private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { name = (Ssortingng) stream.readObject(); // object property address = (Ssortingng) stream.readObject();// object property } 

Quand devrait-il être utilisé à la place d’une autre technique de persistance?

La Serialization intégrée est utile lorsque l’expéditeur et le destinataire sont tous deux Java. Si vous souhaitez éviter ce type de problèmes, nous utilisons XML ou JSON à l’aide de frameworks.

J’ai rencontré ce dilemme il y a environ un mois (voir la question que j’ai posée ).

La principale leçon que j’en ai tirée est l’utilisation de la sérialisation Java uniquement lorsque cela est nécessaire et s’il n’y a pas d’autre option. Comme Jon a dit, il a ses inconvénients, alors que d’autres techniques de sérialisation sont beaucoup plus faciles, plus rapides et plus portables.

La sérialisation signifie que vous placez vos données structurées dans vos classes dans un ordre de code octet pour les sauvegarder.

Vous devez généralement utiliser d’autres techniques que la méthode buildin java, elle est conçue pour fonctionner immédiatement, mais si vous modifiez à l’avenir des contenus ou des ordres dans vos classes sérialisées, vous rencontrez des problèmes car vous ne pouvez pas charger. correctement.

La sérialisation des objects Java (JOS) présente l’avantage de fonctionner. Il existe également des outils qui font la même chose que JOS, mais utilisent un format XML au lieu d’un format binary.

A propos de la longueur: JOS écrit certaines informations de classe au début, au lieu de faire partie de chaque instance. Par exemple, les noms de champs complets sont enregistrés une fois et un index dans cette liste de noms est utilisé pour les instances de la classe. Cela allonge la sortie si vous écrivez une seule instance de la classe, mais est plus efficace si vous en écrivez plusieurs (différentes). Je ne vois pas très bien si votre exemple utilise réellement une classe, mais c’est la raison générale pour laquelle JOS est plus long que prévu.

BTW: ceci est accessoire, mais je ne pense pas que JSON enregistre les noms de classes (comme dans votre exemple), et peut-être qu’il ne fera peut-être pas ce dont vous avez besoin.

Si le stockage en série d’une quantité infime d’informations est relativement important, c’est parce qu’il stocke des informations sur les classes des objects qu’il sérialise. Si vous stockez une copie de votre liste, vous constaterez que le fichier n’a pas beaucoup grandi. Stockez le même object deux fois et la différence est minime.

Les avantages importants sont: relativement facile à utiliser, assez rapide et pouvant évoluer (tout comme XML). Cependant, les données sont plutôt opaques, elles ne concernent que Java, associent étroitement les données à des classes et des données non fiables peuvent facilement provoquer un déni de service. Vous devriez penser à la forme sérialisée plutôt que de simplement gifler les implements Serializable partout.

Si vous n’avez pas trop de données, vous pouvez enregistrer des objects dans un object java.util.Properties. Un exemple de paire clé / valeur serait user_1234_firstname = Peter. L’utilisation de la reflection pour enregistrer et charger des objects peut faciliter les choses.