J2ME-Objektserialisierung: Frameworks im Vergleich

Transcription

J2ME-Objektserialisierung: Frameworks im Vergleich
AKTUELLE THEMEN DER INFORMATIK
J2ME-Objektserialisierung:
Frameworks im Vergleich
Tobias Satzger, CN8
JUNI 2006
1. Einleitung
2. Objektserialisierung
3. J2ME
4. Aktuelles Thema der Informatik
5. Die Frameworks
5.1 RMI Optional Package
5.1.1 RMI
5.1.2 Java-Standardserialisierung
5.2 Burlap/Hessian
5.2.1 Serialisierung
5.3 Javolution
5.3.1 Serialisierung
5.4 kSOAP
6. Vergleich Frameworks
6.1 Instanzierungszeit
6.2 Serialisierungszeit
6.3 Deserialisierungszeit
6.4 Objektgröße in serialisierter Form
6.5 Objekt-Overhead
7. Quellen
S.
S.
S.
S.
S.
S.
S.
S.
S.
S.
S.
S.
S.
S.
S.
S.
S.
S.
S.
S.
3
3
4
5
6
6
6
7
8
8
10
10
11
12
12
13
14
15
15
17
1 Einleitung
Dieser Ausarbeitung liegt der gleichnamige Artikel „J2MEObjektserialisierung: Frameworks im Vergleich“ von Reto Bürki, Raffael
Schärer und Martin Müller zu Grunde. Dieser Artikel ist in dem Magazin
Javaspektrum 1/2006 erschienen.
Ursprünglich wollten die Autoren hierbei die 4 frei verfügbaren Frameworks
Javolution, kSOAP, Burlap/Hessian und RMI Optional Package miteinander
vergleichen. Es wurde eine komplexe Datenstruktur als Testobjekt erstellt,
welches jeweils anhand der zu vergleichenden Frameworks sersialisiert
wurde. Daraus resultierten einige Ergebnisse, die den Benchmark-Test
bildeten. Da das Framework kSOAP nicht in diese Testumgebung integriert
werden konnte, kam schließlich ein Vergleich der übrigen 3 Frameworks
zustande.
2 Objektserialisierung
Die Technik der Objektserialisierung ermöglicht es, in einer Anwendung
erzeugte Objekte, persistent abspeichern zu können. Dieses Konzept ist
also in einer objektorientierten Programmiersprache sehr interessant, da
hier mit eben solchen Ojekten gearbeitet wird.
Durch die persistente Speicherung können Objekte später jederzeit durch
die abgelegten Daten wieder hergestellt werden – sie überleben auf diese
Weise also die Laufzeitumgebung. Außerdem können die serialisierten
Daten über das Netzwerk an eine andere Umgebung transportiert werden,
um dann dort ein entsprechendes Objekt aus den Daten zu erzeugen – was
z.B. gerade für verteilte Anwendungen äußert hilfreich ist.
Um mit einem bestimmten Objekt an einer entfernten Stelle weiterarbeiten
zu können, ist es für die Anwendung also nicht nötig, abhängig vom
aktuellen Kontext, Daten zu identifizieren, die für die diese Situation
relevant sind, und diese Daten dann auf irgendeine Weise abzuspeichern
und an die entsprechende Stelle im Netzwerk zu schicken. Darüber hinaus
müssen die ankommenden Daten noch richtig erkannt und ausgewertet
werden können.
Bei der Objektserialisierung wird durch den Entwickler einmal festgelegt
wie ein serialisierbares Objekt persistent repräsentiert wird, was eine
konsistente und einheitliche Methode ohne weitere Umwege darstellt.
Die Objektserialisierung ist also in der objektorientierten Welt ein wichtiges
Werkzeug.
3 J2ME
J2ME steht für Java 2 Mirco Edition. Dies ist eine im wesentlichen starkt
abgespeckte Variante der üblichen Standard Edition. Diese limitierte Version
kommt daher v.a. auf resourcenarmen Geräten zum Einsatz – z.B. gerade
auf mobilen Endgeräten, wie einem Handy.
Es gibt für bestimmte Anwendungsbereiche, durch eigens für diesen Zweck
bereitstehende Packages, die Möglichkeit den gegebenen Funktionsumfang
der Micro Edition bei Bedarft auf kompfortable Weise erweitertn zu können.
Dazu gehört z.B. das RMI Optional Package, welches eingangs schon
erwähnt wurde und später noch genauer betrachtet wird.
Abb. 3-1, www.sun.com
4 Aktuelles Thema der Informatik
Die Kombination der Objektserialisierung im Einsatz mit kleinen mobilen
Geräten, wird heutzutage schon oftmals verwendet, und wird als
zukunfsträchtiges Gebiet angesehen.
Dies liegt einerseits sicherlich darin begründet, dass objektorientierte
Programmiersprachen in dem Bereich dieser mobilen Geräte immer häufiger
zum Einsatz kommen, und dass es abzusehen ist dass diese Tendenz noch
weiter zunimmt. Bei einigen Handy-Werbungen werden diese u.A. mit ihrer
Java-Fähigkeit angepriesen. Außerdem wird z.B. bei vielen MDE-Geräten,
die mit einem Windows-System ausgestattet sind, mit der ebenfalls
objektorientierten Sprache C# entwickelt.
Andererseits wird den mobilen Anwendungen im Allgemeinen ein enormes
Entwicklungspotential zugeschrieben. Viele Geschäftsbereiche, die ihr
Dasein noch in einer tristen Offline-Welt verbringen müssen, können damit
neu erschlossen werden. Durch die Mobilität der Endgeräte sind deren
Einsatzmöglichkeiten nur wenige Grenzen gesetzt.
V.a. auch im privaten Sektor sind einige Varianten von mobilen
Anwendungen vorstellbar. So sind z.B. Szenarian angedacht, welche das
Handy als universelle Fernbedienung im Haushalt – von der Steuerung des
Fernsehers bis zur Mikrowelle - sehen.
5 Die Frameworks
Bei keinem der zu vergleichenden Frameworks handelt es sich um ein
explizit für die Serialisierung entwickeltes Framework. Neben einigen
anderen Funktionalitäten kann aber über jedes dieser Frameworks eine
Objektserialisierung im J2ME-Umfeld realisiert werden. Im folgenden
werden die einzelnen Frameworks näher beschrieben.
5.1 RMI Optional Package
Das RMI Optional Package ist eine Erweiterung der J2ME CDC
Konfiguration, welches die RMI-Funktionaltät (Remote Method
Invocation) hinzufügt (vgl. Abb. 3-1), weil dieses nicht von vornherein
bei der Micro Edition vorhanden ist.
5.1.1 RMI
RMI ist die Möglichkeit in Java, entfernte Funktionalitäten mit
einem hohen Abstraktionnivaeu zu nutzen. Es können Objekte
auf einem Server angesprochen werden, als ob diese lokal
vorhanden wären.
Um entfernte Objekte wie lokale erscheinen zu lassen, wird mit
sog. Stellvertreterobjekten bzw. Proxies gearbeitet.
Lokal kann so z.B. eine Methode des Proxy-Objekts ausgeführt,
und das Ergebnis zurückerhalten werden. Die Berechnung des
Ergebnisses wird tatsächlich aber an anderer Stelle
durchgeführt. Das Stellvertreterobjekt leitet die Anfrage
nämlich seinerseits an die entsprechende Stelle weiter, und gibt
schließlich das erhaltene Resultat an den Aufrufer zurück.
Innerhalb der Methode des Stellvertreter wird also nicht das
eigentliche Funktionsangebot ausgeführt, sondern die
Kommunikation, um die eigentliche Funktion an jener
entfernten Stelle abarbeiten zu lassen, wo sie implementiert
wurde. Der Client nutzt die Proxy-Objekte lokal, ohne sich
dafür interessieren zu müssen wo letztendlich die Arbeit
verrichtet wird.
5.1.2 Java-Standardserialisierung
Die Proxy-Objekte müssen natürlich auch die Ein-/
Rückgabeobjekte an die/von den entfernten Objekte weiter-/
zurückgeben, die für bestimmte Methoden erforderlich sind. So
muss beispielsweise ein String-Objekt „person“ bei folgender
Beispiel-Methode über das Netzwerk gesendet werden:
public int getId(String person)
Listing 5.1.2-1
Hierbei spielt die Objektserialisierung eine tragende Rolle bei
RMI. Diese ermöglicht es Objekte in ein persistentes Format zu
bringen, welches schließlich über das Netzwerk gesendet
werden kann. An der Gegenstelle werden die Objekte dann per
Deserialisierung restauriert.
Der RMI-Mechanismus greif dabei auf die JavaStandardserialisierung (Java Object Serialization – JOS) zurück,
welche die Objekte in ein binäres Format ablegt.
Ein Objekt kann anhand der writeObject-Methode der
ObjectOutputStream-Klasse auf diese Weise serialisiert werden.
Der ObjectoutputStream-Klasse wird der OutputStream
übergeben, in welche das Objekt geschrieben werden soll. Um
in der Welt von RMI zu bleiben, soll dies ein NetzwerkDatenstrom sein:
String person = „Person“;
// Netzwerk-Ausgangsstrom
Socket socket = new Socket(host, port);
OutputStream socketOutStream = socket.getOutputStream();
// Verbindung zw. Objekt-Ausgangsstrom und Netzwerk-Strom herstellen
ObjectOutputStream objOutStream =
new ObjectOutputStream(socketOutStream);
// serialisieren
objOutStream.writeObject(person);
Listing 5.1.2-2
Um Objekte serialisieren zu können, müssen diese die
Markierungsschnittstelle Serializable implementieren. Die
Klasse String aus Listing 5.1.2-2 erfüllt diese Anforderung, wie
auch viele andere der vordefinierten Klassen. Es gibt allerdings
auch Exemplare, welche diese Implementierung nicht
aufweisen, weil deren Serialisierung u.U. auch gar nicht klar
wäre. Z.B. ist dies bei der Klasse Thread der Fall.
Soll eine eigene Klasse serialisiert werden können, muss diese
also ebenfalls Serializable sein. Wird ein Objekt serialisiert, so
müssen auch all deren Attribute mit abgespeichert werden,
damit das Objekt bei der Wiederherstellung den
abzuspeichernden Zustand wieder annehmen kann. Bei der
Standardserialisierung wird deshalb der gesamte Objektbaum
durchlaufen, damit keine relevanten Daten aussen vor
gelassen werden.
Der Entwickler kann bei seinen Klassen auch selbst hinterlegen,
welche Ausgabe deren Objekte bei der Serialisierung erzeugen
und wie entsprechend bei der Deserialisierung vorgegangen
wird.
5.2 Burlap/Hessian
Burlap und Hessian sind zwei Protokolle, um Web Service
verbinden zu können. Die beiden Varianten unterscheiden sich
dadurch, dass Burlap durch die Serialisierung ein XML-Format
erzeugt und Hessian hingegen ein binäres Format.
Für dieses Protokolle sind Implementierungen für verschiedene
Plattformen verfügbar (Java, Python, C++, .NET C#, PHP, Ruby).
Die Protokolle weisen ebenfalls eine geringe Grösse auf und
eignen sich daher für den Einsatz auf J2ME-Umgebungen.
5.2.1 Serialisierung
Dieses Framework unterstützt die Java-Serialisation und
erfordert daher nicht das Ausgabeformat explizit festzulegen.
Alle üblichen Java-Klassen können auch mit Burlap/Hessian
serialisiert werden.
Der Serialisierungvorgang wird analog zu dem aus der JavaStandardserialisierung angestossen (vgl. 5.1.2-2). Das Objekt
ObjectoutputStream wird aber – je nach Variante – durch ein
HessianOutput- bzw. BurlapOutput-Objekt ersetzt:
String person = „Person“;
// Netzwerk-Ausgangsstrom
Socket socket = new Socket(host, port);
OutputStream socketOutStream = socket.getOutputStream();
// Verbindung zw. Objekt-Ausgangsstrom und Netzwerk-Strom herstellen
HessianOutput hessianOut =
new HessianOutput(socketOutStream);
// serialisieren
hessianOut.writeObject(person);
Listing 5.2.1-1
// ...
BurlapOutput burlapOut =
new BurlapOutput(socketOutStream);
// ...
Listing 5.2.1-2
Die binäre Version Hessian kann sogar mit einer kompakten
Micro-Variante genutzt werden. Diese Variante kann mit Hilfe
von nur 5 Hessian-Klassen verwendet werden, was sich z.B. v.a.
bei dem Einsatz auf Handys eignet. Das folgende Beispiel der
Hessian-Dokumentation zeigt, wie somit ein entfernter Service
genutzt werden kann:
Abb. 5.2.1-3
5.3 Javolution
Dieses Framework ist hauptsächlich für Echtzeit- und EmbeddedSysteme gedacht. So werden mit diesem Framework einige Klassen
ausgeliefert, die gegenüber den bestehenden Klassen der Java Mirco
bzw. Standard Edition so manche Vorteile v.a. hinsichtlich der
Geschwindigkeit versprechen. In der Dokumentation der Javolution
Klasse FastTable ist folgender Vergleich zu finden:
Abb. 5.3-1, www.javolution.org
U.a. besitzt Javolution einen sehr schnellen XML-Parser, der
hinsichtlich der Serialisierung noch von Interesse sein wird.
Das Framework kann sowohl auf der Mirco wie auch in Verbindung
mit der Standard Edition verwendet werden.
5.3.1 Serialisierung
Die Serialisierung, wie es dieses Framework vorsieht, geschieht
über die Methode write, der Javolution-Klasse ObjectWriter.
An diese Methode wird das zu serialisierende Objekt
übergeben, sowie der OutputStream, in welches die Daten
geschrieben werden:
String person = „Person“;
// Netzwerk-Ausgangsstrom
Socket socket = new Socket(host, port);
OutputStream socketOutStream = socket.getOutputStream();
// serialisieren
ObjectWriter<String> personWriter =
new ObjectWriter<String>();
personWriter.write(person, socketOutStream);
Listing 5.3.1-1
Im inneren der write Methode wird nach einem eigenen Format
serialisiert, welches durch ein XMLFormat-Objekt von Javolution
festgelegt ist.
Jeder Klasse kann dabei ein eigenes XMLFormat-Objekt
zugeordnet werden. In der Dokumentation von Javolution wird
empfohlen ein XMLFormat für eine eigene Klasse über eine
statische Instanz festzulegen. Beispielhaft soll dies anhand der
Klasse Point veranschaulicht werden:
Abb. 5.3.1-2, www.javolution.org
Ist zu einer Instanz einer bestimmte Klasse kein
entsprechendes XMLFormat-Objekt vorhanden, so wird
innerhalb des Schreibvorgangs ein passendes XMLFormat
innerhalb der Vererbungshierarchie gesucht. Letzten Endes
kann immer noch das XMLFormat der Klasse Object
herangezogen werden, welches aber keine
Standardserialisierung durchführt.
Bei dem Serialisierungsvorgang wird also schließlich – dem
festgelegten Format entsprechend – ein XML-Dokument
erzeugt, welches dann das Objekt repräsentiert. Wie einleitend
schon angedeutet wird intern ein XML-Parser des JavolutionFrameworks verwendet, um das Dokument zu erstellen und
auszuwerten.
5.4 kSOAP
Wie der Name bereits vermuten lässt verwendet dieses
Framework den Standard SOAP. Dieser ist – neben RMI – auch eine
Methode um die Kommunikation von verteilten Anwendungen zu
realisieren. SOAP verwendet dabei die etablierten Web-Standards
HTML und XML.
Viele existierende SOAP-Frameworks können bei mobilen
Anwendungen nicht eingesetzt werden, weil diese schlicht die
Speichergrösse der üblichen Geräte sprengen. kSOAP ist
deshalb gerade für den Einsatz mit der Java Micro Edition
entwickelt worden und umgeht diese Problematik daher vom
Ansatz her.
Da kSOAP – wie bereits erwähnt – nicht in die Testumgebung
integriert werden konnte, ist leider kein Vergleich zu den
anderen Frameworks möglich gewesen.
6 Vergleich der Frameworks
Zur Durchführung der Tests wurde folgendes Referenzobjekt
angelegt:
Abb. 6-1
Darauf basierend wurden die Test durchgeführt, die in 6.1 – 6.5
aufgeführt sind. Die Erklärungen hierzu wurden aus dem Artikel
entnommen.
6.1 Instanzierungszeit
Die Instanzierungszeit (in Nanosekunden) „bezeichnet die Zeit, die
zur Instanzierung des komplexen Objektes benötigt wird.
Abb. 6.1-1: Instanzierungszeit
„Bei der Instanzierungszeit fiel vor allem auf, dass die Virtuelle
Maschine eine gewisse Anlaufzeit bei der Objektinstanzierung
benötigt und dort die Werte entsprechend hoch ausfallen. Dies lässt
sich darauf zurückführen, dass der Just in Time Compiler (JIT) bei der
ersten Instanzierung des Objektes zuerst aus dem Java-Bytecode
ausführbaren Maschinencode generieren muss. Bei weiteren
Instanzierungen des Objektes wird dieser Schritt nicht mehr benötigt,
da der Maschinencode im Speicher schon vorhanden ist.
Hessian und Burlap (s. Abb. 6.1-1) scheiden fast gleich ab, was nicht
verwundert, da diese Frameworks die gleichen Objektdefinitionen
verwenden. Javolution erzeugt eindeutig die schwergewichtigsten
Objekte, die einen sehr hohen Instanzierungszeit vor allem bei der
ersten Instanzierung benötigt. Dies liegt daran, dass das Framework
zuerst die Formatierungsinformationen für die jeweiligen Objekte
verarbeiten muss.“
6.2 Serialisierungszeit
Die Serialisierungszeit (in Millisekunden) „bezeichnet die Zeit,die
nötig ist, um das Objekt vom Speicher in einen Strom zu
serialisieren.“
Abb. 6.2-1: Serialisierungszeit
„Bei diesem Test fällt vor allem auf, dass Javolution sehr schnell
serialisiert, obwohl es XML als Darstellungsform für die Serialisierung
verwendet (s. Abb. 6.2-1). Javolution serialisiert Objekte fast gleich
schnell wie RMI, das seine Objekte in optimierter, binärer Form
speichert. Diese Messungen stimmen auch mit den Ergebnissen der
Benchmarks der Javolution-Entwickler überein. Was das Framework
bei der Instanzierung der Objekte durch die
Formatierungsinformationen verliert, macht es bei der Serialisierung
wieder gut. Anders als bei Burlap und Hessian steigt bei RMI und
Javolution die Zeit für die Objektserialisierung nicht an, obwohl die
Größe der Objekte massiv zunimmt. Hessian und Burlap zeigen einen
linearen Anstieg der Serialisierungszeit, wobei Burlap aufgrund der
XML-Codierung langsamer ist.
Am schnellsten serialisiert RMI die Objekte. Die hohe Performance von
RMI fällt in allen Tests auf. Die liegt vor allem an den effizienten
Algorithmen und der optimalen Ausnutzung der Funktionalität von
Java.“
6.3 Deserialisierungszeit
Die Deserialisierungszeit „bezeichnet die Zeit, die das jeweilige
Framework benötigt, um das serialisierte Objekt wieder aus dem
Strom zu deserialisieren.“
„Das Resultat dieses Tests ist analog zum Resultat des Tests
Serialisierungszeit. Wieder glänzen Javolution und RMI mit konstanten
Zeiten, obwohl die Objektkomplexität zunimmt. Auch Hessian und
Burlap verhalten sich analog.“
6.4 Objektgrösse in serialisierter Form
Die Objektgrösse in serialisierter Form (in Kilobytes) „bestimmt die
Größe, die das Objekt in serialisierter Form im Strom benötigt.“
Abb. 6.4-1: Objektgrösse in serialisierter Form
„In Abbildung 6.4-1 fällt auf, dass trotz zunehmender Objektgrösse
bei RMI die Größe der Daten in serialisierter Form nicht in gleichem
Maße zunimmt wie bei den anderen drei getesteten Frameworks.
Burlap schneidet auch hier am schlechtesten ab. Die liegt daran, dass
Burlap SML (Simple Markup Language, einfacheres XML) für die
Darstellung der serialisierten Daten verwendet. Dies verursacht
längere Tags und Redundanzen durch Wiederholung.
Hier zeigt sich eindeutig, dass die binären Protokolle in dieser
Disziplin klar überlegen sind, da diese Darstellung deutlich kürzere
Identifikationstags erzeugt. Anstatt <Integer> zum Bezeichnen eines
Integer-Wertes reicht bei Hessian ein I.“
6.5 Objekt-Overhead
Der Objekt-Overhead (in Kilobytes in %) „bestimmt den Overhead des
Objektes. Der Overhead berechnet sich aus der Differenz der
Objektgröße im Arbeitsspeicher zur Objektgröße in serialisierter
Form.“
Abb. 6.5-1: Objekt-Overhead
„Abbildung 6.5-1 zeigt, dass auch hier die Frameworks effizienter
sind, die binäre Technik verwenden. Ein interessanter Effekt stellt
sich bei RMI ein, bei dem der Overhead mit zunehmender
Objektkomplexität abnimmt. RMI ersetzt beim Marshalling Objekte
mit gleichem Inhalt durch Referenzen, was zu einer sehr kompakten
Darstellung führt.
An der Spitze liegt RMI mit einem sinkenden Overhead. Der unter den
Nullpunkt sinkende Wert bedeutet, dass bei RMI mit zunehmender
Objektgrösse die Darstellung im serialisierter Form kleiner ist als die
Größe des Objekts im Speicher. Man kann hier also von einer
Kompression der serialisierten Daten sprechen.
Hessian weist einen Overhead von ca. 26 % auf. Das heißt, ungefähr
ein Viertel des serialisierten Datenvolumens wird vom Protokoll
beansprucht. Die beiden XML-basierte Protokolle weisen einen hohen
Overhead von 50 % (Javolution) bis 61 % (Burlap) auf.“
7 Quellen
•
R. Bürki, R Schärer, M. Müller: J2ME-Objektserialisierung: Frameworks im
Vergleich, Javaspektrum 1/2006
•
[Hessian/Burlap] www.caucho.com
•
[Javolution] www.javolution.org
•
[kSOAP] kobjects.sourceforge.net/ksoap2
•
www.sun.com
•
J. Zobel, Mobile Business und M-Commerce, Hanser 2001
•
C. Ullenboom: Java ist auch eine Insel