Warum ich keine Java-Serialisierung benutze

You can find the english version of this article at https://medium.com/@procster/why-i-dont-use-java-serialization-5ae0e98e641a

Java besitzt eine, auf den ersten Blick, komfortable Funktion, um Objekte zu serialisieren. Dadurch können Objekte gespeichert oder auch übertragen werden. Diese Funktion ist jedoch nur sehr eingeschränkt nutzbar. Warum das so ist, möchte ich in diesem Artikel aufzeigen.

Lesbarkeit

Oft sollen serialisierte Objekte über das Netzwerk übertragen werden. Hier wäre es von Vorteil, wenn man die übertragenen Daten auch auf dem Weg durch das Netzwerk lesen kann. Dies ist beispielsweise bei der Fehlersuche hilfreich. Leider ist das bei der Java-Serialisierung nicht gegeben.

Im folgenden ein Beispiel, welches ein simples Objekt serialisiert:

    Customer c = new Customer();
    c.setName("Mustermann");
    c.setPrename("Max");
    c.setStreet("Musterstraße");
    c.setHousenumber(1);
    c.setZip(12345);
    c.setCity("Musterhausen");

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    
    ObjectOutputStream oos = new ObjectOutputStream(os);
    oos.writeObject(c);
    System.out.println(os.toString());

Die Ausgabe liest sich wie folgt:

��
Mustermannt
Musterstraße

Nicht nur, dass hier Teile fehlen, weil die Zeichenkette durch Steuerzeichen in der Ausgabe verfälscht wird. Auch das, was lesbar ist lässt sich nur schwer analysieren.

Dem gegenüber ein Beispiel, welches das Objekt als XML serialisiert:

    Customer c = new Customer();
    c.setName("Mustermann");
    c.setPrename("Max");
    c.setStreet("Musterstraße");
    c.setHousenumber(1);
    c.setZip(12345);
    c.setCity("Musterhausen");

    ByteArrayOutputStream os = new ByteArrayOutputStream();

    JAXB.marshal(c, os);
    System.out.println(os.toString());

Hier liest sich die Ausgabe wie folgt:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer>
    <city>Musterhausen</city>
    <housenumber>1</housenumber>
    <name>Mustermann</name>
    <prename>Max</prename>
    <street>Musterstraße</street>
    <zip>12345</zip>
</customer>

Hier kann man sofort sehen, was genau übertragen wurde. Man kann sehen, welche Felder gesetzt sind und welche Daten diese beinhalten. Diese vereinfacht die Fehlersuche.

Interoperabilität

Ein weiteres Problem mit der Java-Serialisierung ist der Datenaustausch mit Software, welche nicht in Java geschrieben wurde. Wärend XML von den meisten Programmiersprachen unterstützt wird, ist die Java-Serialisierung JVM-Sprachen vorbehalten. Das macht einen Datenaustausch mit anderen Programmen sehr schwer.

Auch Apache ActiveMQ, ein Message Broker, unterstützt seit Version 5.12.2 bzw. 5.13.0 nativ serialisierte Objekte nur noch, wenn dies vorher explizit konfiguriert wurde.

Datenvalidierung

Oft sollen die ausgetauschten Daten bestimmten Anforderungen entsprechen. Ein Name sollte mit einem Großbuchstaben beginnen oder die Postleitzahl einem bestimmten Format entsprechen. Dies ist nur mit der Java-Serialisierung nicht überprüfbar. Bei XML hingegen können im Schema entsprechende Restriktionen definiert werden, was die Validierung der Daten vereinfacht.

Fazit

Auch wenn die Java-Serialisierung einfach zu nutzen ist, so gibt es heute bessere Alternativen, insbesondere, wenn es um den Datenaustausch zwischen mehreren Systemen geht. XML hat sich inzwischen als ein Standard etabliert und ist, dank JAXB, auch nicht komplizierter zu nutzen.

Auch die Tatsache, dass XML etwas größere Datenmengen erzeugt (in dem Beispiel hier 253 Byte gegenüber der Java-Serialisierung mit 176 Byte) ist das oft vernachlässigbar. Wenn XML doch zu groß für den Anwendungsfall ist, so gibt es aber auch hier bessere Alternativen, wie Beispielsweise “Protocol Buffers”.

Daher wäre für mich der einzige Fall, bei dem ich die Java-Serialisierung nutzen würde, das Speichern von Daten in einer Datei, welche von dem gleichen Program wieder gelesen werden soll, sofern es zu kompliziert wäre ein eigenes Dateiformat hierfür zu schreiben und XML zu groß wäre.