13 Stimmen

Wie man mit den am häufigsten fehlenden Klassen in J2ME umgeht

Ich versuche, eine Anwendung zu programmieren, die auf verschiedenen Java-Plattformen wie J2SE, J2ME, Android usw. läuft. Ich weiß bereits, dass ich den größten Teil der Benutzeroberfläche für jede Plattform neu schreiben muss, aber ich möchte die Kernlogik wiederverwenden.

Die Übertragbarkeit dieses Kerns birgt drei Nachteile, die mir bekannt sind:

  1. Beibehaltung der alten Java 1.4-Syntax keine der schönen Sprachfunktionen von Java 5.0 zu nutzen
  2. nur mit externe Bibliotheken die bekanntermaßen auf diesen Plattformen funktionieren (d.h.: kein JNI verwenden und keine Abhängigkeiten zu anderen Bibliotheken haben, die diese Regeln verletzen)
  3. nur unter Verwendung der Klassen, die vorhanden sind auf all diesen Plattformen

Ich kenne Wege zur Überwindung (1) : Code im 5.0-Stil und automatische Konvertierung nach 1.4 ( retroweaver - Ich habe es noch nicht ausprobiert, aber es scheint in Ordnung zu sein).

Ich denke (2) ist ein Problem, das ich einfach akzeptieren muss.

Jetzt würde ich gerne wissen, was die beste Lösung ist für (3) vor allem die Sammelkurse, die ich am meisten vermisse. Ich kann an diese denken:

  • Die meisten Programmierer, die ich kenne, verwenden einfach keine Set , Map , List , usw. und Rückgriff auf Vector und einfache Arrays. Ich denke, das macht den Code von vornherein hässlich. Aber ich weiß auch, dass die richtige Wahl zwischen TreeSet/Hashset o LinkedList/ArrayList ist entscheidend für die Leistung, und immer mit Vector und Arrays können nicht richtig sein.
  • Ich könnte meine eigenen Implementierungen dieser Klassen programmieren. Dies scheint das Rad neu zu erfinden, und ich denke, ich könnte es nicht so gut machen, wie andere es getan haben.
  • Da Java Open Source ist, könnte ich den Quellcode des J2SE Collections Frameworks nehmen und in meine Anwendung einbauen, wenn ich sie für J2ME erstelle. Ich weiß allerdings nicht, ob das eine gute Idee ist. Vielleicht gibt es gute Gründe, dies nicht zu tun.
  • Vielleicht gibt es bereits Bibliotheken, die die wichtigsten Funktionen des Collections-Frameworks nachbilden, aber für Low-End-Systeme optimiert sind, indem sie vielleicht Funktionen nicht implementieren, die nur selten genutzt werden. Kennen Sie welche?

Vielen Dank für Ihre Antworten und Meinungen!

Bearbeiten: Ich habe schließlich eine (komplexe, aber schöne) Lösung gefunden, und ich dachte, wenn ich meine eigene Antwort gebe und sie akzeptiere, würde die Lösung oben sichtbar werden. Aber das Gegenteil ist der Fall, meine Antwort steht immer noch ganz unten.

13voto

jjb Punkte 3532

J2ME ist brutal, und Sie werden sich damit abfinden müssen, auf einige der Annehmlichkeiten anderer Plattformen zu verzichten. Gewöhnen Sie sich an Hashtable und Vector, und schreiben Sie Ihre eigenen Wrapper auf diese. Machen Sie auch nicht den Fehler anzunehmen, dass J2ME ein Standard ist, denn die JVM jedes Herstellers kann Dinge auf sehr unterschiedliche Weise tun. Ich würde mir anfangs keine großen Sorgen um die Leistung machen, da die Korrektheit von J2ME bereits eine Herausforderung darstellt. Es ist möglich, eine Anwendung zu schreiben, die auf J2ME, J2SE und Android läuft, wie ich es getan habe, aber es erfordert eine Menge Arbeit. Ein Vorschlag, den ich habe, ist, dass Sie den Kern Ihrer Anwendungslogik schreiben und ihn strikt auf java.lang, java.util und java.io beschränken. Überall dort, wo Sie etwas tun, das mit der Plattform interagieren könnte, wie z. B. das Dateisystem oder das Netzwerk, können Sie eine Schnittstelle erstellen, mit der Ihr Kernanwendungscode interagiert und die Sie für die verschiedenen Umgebungen unterschiedlich implementieren. Sie können zum Beispiel eine Schnittstelle haben, die HTTP-Zeug umhüllt und javax.microedition.io.HttpConnection mit J2ME und java.net.HttpURLConnection auf Android verwendet. Es ist zwar mühsam, aber wenn Sie eine App auf allen drei Umgebungen betreiben wollen, können Sie damit Ihr Ziel erreichen. Viel Glück!

12voto

Lena Schimmel Punkte 7094

Es ist schon eine Weile her, dass ich diese Frage gestellt habe, und es ist auch schon eine Weile her, dass ich eine gute, funktionierende Lösung für das Problem gefunden habe, aber ich hatte vergessen, Ihnen davon zu erzählen.

Mein Hauptaugenmerk lag auf dem Java Collections Framework, das Teil der java.util Paket.

Ich habe endlich den Quellcode von Suns Java 6.0 genommen und alle Klassen, die zum Collections Framework gehören, in ein eigenes Projekt kopiert. Dies war ein Java 6.0 Projekt, aber ich habe die Jars von J2ME als Klassenpfad verwendet. Die meisten dieser Klassen, die ich kopiert habe, hängen von anderen J2SE-Klassen ab, so dass es kaputte Abhängigkeiten gibt. Wie auch immer, es war recht einfach, diese Abhängigkeiten zu reduzieren, indem ich alles weggelassen habe, was mit Serialisierung zu tun hat (was für mich keine Priorität hat) und einige kleinere Anpassungen vorgenommen habe.

Ich habe das Ganze mit einem Java 6-Compiler kompiliert, und retrotranslator wurde verwendet, um den resultierenden Bytecode zurück nach Java 1.2 zu portieren.

Das nächste Problem ist der Paketname, denn man kann keine Klassen aus java.util mit einer J2ME-Anwendung zu laden - der Bootstrap-Klassenlader schaut nicht in die jar-Datei der Anwendung, die anderen Bootloader dürfen nichts mit diesem Paketnamen laden, und bei J2ME kann man keine eigenen Klassenlader definieren. Retrotranslator konvertiert nicht nur Bytecode, sondern hilft auch dabei, Namensreferenzen in bestehendem Bytecode zu ändern. Ich musste alle Klassen in meinem Projekt verschieben und umbenennen, z.B. java.util.TreeMap wurde my.company.backport.java.util.TreeMap_ .

Ich war dann in der Lage, die eigentliche J2ME-Anwendung in einem zweiten Java 6.0-Projekt zu schreiben, das auf die üblichen java.util.TreeMap mit der generischen Syntax, um typsichere Sammlungen zu erstellen, kompilieren Sie diese Anwendung in Java 6.0-Bytecode und lassen Sie sie durch den Retrotranslator laufen, um Java 1.2-Code zu erstellen, der nun auf my.company.backport.java.util.TreeMap_ . Beachten Sie, dass TreeMap ist nur ein Beispiel, es funktioniert tatsächlich für das gesamte Collections-Framework und sogar für J2SE-Jars von Drittanbietern, die auf dieses Framework verweisen.

Die resultierende Anwendung kann als jar- und jad-Datei verpackt werden und läuft sowohl auf J2ME-Emulatoren als auch auf aktuellen Geräten (getestet auf einem Sony Ericsson W880i).

Der ganze Prozess scheint ziemlich komplex zu sein, aber da ich Ant für die Build-Automatisierung verwendet habe und ich Retranslator sowieso brauchte, gab es nur einen einmaligen Overhead für die Einrichtung des Collection Framework Backports.

Wie oben erwähnt, habe ich dies vor fast einem Jahr getan und schreibe dies hauptsächlich aus dem Kopf, daher hoffe ich, dass es keine Fehler enthält. Wenn Sie an weiteren Details interessiert sind, hinterlassen Sie mir einen Kommentar. Ich habe ein paar Seiten deutscher Dokumentation über diesen Prozess, die ich zur Verfügung stellen könnte, wenn es eine Nachfrage gibt.

3voto

Sean Owen Punkte 64909

Genau mit dieser Situation waren wir bei der Entwicklung von zxing . Wenn J2ME auf Ihrer Zielliste steht, ist dies bei weitem Ihr limitierender Faktor. Wir haben uns für MIDP 2.0 / CLDC 1.1 entschieden. Wenn Sie eine ähnliche Anforderung haben, müssen Sie sich an Java 1.2 halten. Java 1.4 Sprachfunktionen sind definitiv nicht vorhanden (wie Assert) und im Allgemeinen werden Sie in J2ME nichts nach 1.2 finden.

Wir haben keine externen Bibliotheken verwendet, aber Sie könnten sie ohne Probleme in Ihre bereitgestellte .jar-Datei packen. Es würde die resultierende .jar-Datei größer machen, und das könnte ein Problem sein. (Dann können Sie Optimierer/Shrinker wie ProGuard einsetzen, um dieses Problem zu entschärfen).

Am Ende habe ich etwas wie Collections.sort() und Comparator neu implementiert, da wir sie brauchten und sie nicht in J2ME enthalten sind. Also ja, Sie könnten in Betracht ziehen, dies in Fällen zu tun, wenn auch nur, wenn nötig.

Wir haben Vector und Hashtable und Arrays verwendet, da es in J2ME keine andere Möglichkeit gibt. Ich würde sie einfach verwenden, es sei denn, Sie haben einen Grund, es nicht zu tun, und das wäre die Leistung, denke ich. Theoretisch optimieren die JVM-Hersteller bereits ihre Implementierung, aber das bedeutet nicht, dass man nicht eine bessere machen könnte... Ich wäre überrascht, wenn es sich in den allermeisten Fällen lohnen würde. Stellen Sie einfach sicher, dass Sie das wirklich brauchen, bevor Sie den Aufwand betreiben.

2voto

BenM Punkte 4006

Um einen Teil Ihrer Frage zu beantworten, wäre eine weitere Sammlungsbibliothek Javolution die für j2me erstellt werden können.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X