Westfälische Wilhelms-Universität Münster Ausarbeitung Architektur und Sprachumfang der JVM, KVM und CVM im Rahmen des Skiseminars „Mobile Java“ Björn Böhmer Themensteller: Prof. Dr. Herbert Kuchen Betreuer: Michael Poldner Institut für Wirtschaftsinformatik Praktische Informatik in der Wirtschaft Inhaltsverzeichnis 1 Einleitung................................................................................................................... 3 2 Einführung in die Java Mobile Edition...................................................................... 4 3 2.1 Konfigurationen und Profile ............................................................................. 4 2.2 Spezielle Konfigurationen: CLDC und CDC ................................................... 6 Virtuelle Maschinen für die Java Mobile Edition...................................................... 7 3.1 3.1.1 3.1.2 3.2 3.2.1 3.2.2 3.2.3 3.2.4 3.3 4 Architektur der Java Virtual Machine .............................................................. 7 Unterstützende Aufgaben der JVM .............................................................. 8 Lebenszyklus der JVM während der Ausführung ...................................... 12 Die Kilobyte Virtual Machine ........................................................................ 15 Hardwareanforderungen der KVM ............................................................. 15 Einschränkungen gegenüber der Java Virtual Machine ............................. 16 Aufgehobene Einschränkungen der CLDC 1.1 gegenüber der CLDC 1.0 21 Spezielle Erweiterungen für die KVM ....................................................... 21 Java Card Virtual Machine (CVM) ................................................................ 22 Zusammenfassung und Ausblick............................................................................. 24 Literaturverzeichnis ........................................................................................................ 26 II Kapitel 1: Einleitung 1 Einleitung Die Java Virtual Machine (JVM) ist das entscheidende Bindeglied, um JavaAnwendungen auf verschiedensten Plattformen lauffähig zu gestalten. Durch die Abstraktion von der Hardware und dem Betriebssystem ermöglichen sie eine plattformunabhängige Ausführung der Programme. Nicht zuletzt durch die Entwicklung der virtuellen Maschinen nimmt die Java-Programmiersprache eine bedeutende Rolle im Bereich der Softwareentwicklung ein. Besonders im Bereich von Desktop- und Serveranwendungen finden Java-Anwendungen mit angepassten Laufzeitumgebungen seit vielen Jahren eine weite Verbreitung. Aufgrund der technologischen Weiterentwicklung mobiler Endgeräte und deren starker Verbreitung hat sich neben den Desktop- und Serversystemen ein weiterer Entwicklungsbereich für Java-Programme gebildet. Durch die auf die verschiedenen Formate der Endgeräte angepasste Laufzeitumgebungen sind Java-Applikationen mittlerweile auch in diesem Bereich häufig anzutreffen. Die verschiedenen Laufzeitumgebungen werden dabei unter dem Begriff Java Mobile Edition zusammengefasst. Auch hier spielen virtuelle Maschinen eine zentrale Rolle, jedoch ist eine Wiederverwendung vorhandener virtueller Maschinen aufgrund von Hardwarerestriktionen nicht auf jeder Klasse von Endgeräten möglich. Daher definieren die verschiedenen Laufzeitumgebungen auch zum Teil eigene virtuelle Maschinen. Diese Ausarbeitung legt den Fokus auf die im Bereich der Java Mobile Edition eingesetzten virtuellen Maschinen. Zuvor wird einleitend in Kapitel 2 ein Überblick über die Java Mobile Edition und deren Laufzeitumgebungen gegeben. Im anschließenden Kapitel werden die Architekturen der unterschiedlichen virtuellen Maschinen vorgestellt und miteinander verglichen. Der Schwerpunkt liegt zunächst auf der Beschreibung der Architekturbestandteilen der ursprünglichen Java Virtual Machine anhand ihrer Spezifikation. Darauf aufbauend erfolgt die Analyse weiterer virtueller Maschinen, die auf Basis der JVM für den Einsatz auf limitierten Hardwareressourcen entwickelt wurden. Das abschließende Kapitel stellt eine kritische Zusammenfassung und einen Ausblick auf die weitere Entwicklung in diesem Bereich bereit. 3 Kapitel 2: Einführung in die Java Mobile Edition 2 Einführung in die Java Mobile Edition Die Java Mobile Edition (Java-ME) ist eine auf die Limitationen der mobilen Endgeräte angepasste Version der Java Laufzeitumgebung. Sie ist als eine Menge von Spezifikationen und Technologien zu verstehen, die speziell auf die mobilen Endgeräte zugeschnitten ist. Java-ME erweitert dadurch den Einsatzbereich von Java. Neben den Java-Versionen für Desktopanwendungen sowie der Enterprise-Version zur Entwicklung von Serveranwendungen wird ein zusätzlicher Anwendungsbereich für mobile Geräte erschlossen. Durch die Vielzahl und Vielfalt dieser Geräte sind Flexibilität und Anpassungsfähigkeit entscheidende Faktoren für Laufzeitumgebungen in diesem Bereich. Die Architektur von Java-ME entspricht diesen Kriterien. Die Aufteilung der Laufzeitumgebung in Konfigurationen und Profile garantiert Modularität und skalierbare Hardwareanforderungen. Es gibt daher nicht eine Laufzeitumgebung für eine Geräteklasse, vielmehr bilden die Kombinationen von Konfigurationen und Profilen jeweils eine eigene Laufzeitumgebung [Br06 S. 19 f.]. Abb. 2.1: Übersicht Java Laufzeitumgebungen [Su00a S.10] 2.1 Konfigurationen und Profile Eine Konfiguration besteht aus einer virtuellen Maschine und einem minimalen Satz von Klassenbibliotheken. Sie setzt auf das jeweilige Betriebssystem eines Endgeräts auf. Die verwendete virtuelle Maschine ist dabei auf die jeweilige Gerätekategorie abgestimmt. 4 Kapitel 2: Einführung in die Java Mobile Edition Bei der Java-ME ist die Spezifikationen einer Konfiguration im Wesentlichen abhängig von der eingesetzten virtuellen Maschine. Die Anzahl der Bibliotheken einer Konfiguration ist bewusst klein gehalten, um einer möglichst großen Bandbreite von Geräten einheitliche Grundfunktionalitäten zur Verfügung stellen zu können. Dadurch ist eine Konfiguration als kleinster gemeinsamer Nenner von Plattformeigenschaften und Klassenbibliotheken zu sehen, der auf allen Geräten einer Konfigurationskategorie zur Verfügung steht. Als Konsequenz dieser Beschränkung auf Grundfunktionalitäten ist die Erstellung mobiler Java-Anwendungen lediglich auf Basis von Konfigurationen nicht praktikabel. Daher werden als Ergänzung Profile angeboten, die den Funktionsumfang der Konfigurationen in Form von zusätzlichen Klassenbibliotheken erweitern. Diese Profile werden im Hinblick für einen Anwendungsbereich oder für eine spezielle Gruppe von Geräten entwickelt. Abb. 2.2: Java ME Software Ebenen [Su00a S.6] Durch die Aufteilung der Laufzeitumgebung ist es möglich Java-ME an die Entwicklung neuer Endgeräte anzupassen. Virtuelle Maschinen, Konfigurationen und Profile können für verschiedenste Anforderungen optimiert und angepasst werden. Die Spezifizierung dieser Einheiten wird durch den Java Community Process (JCP) vorgenommen [Su00a S.11 ff.]. Der JCP ist ein organisatorischer Rahmen, der die kooperative Arbeit an Spezifikationen im Java-Umfeld instituiert. Er ermöglicht es in vielen Fällen, trotz unterschiedlicher Interessen von Herstellern allgemein akzeptierte Standards zu finden. Sowohl Firmen und Organisationen als auch interessierte Einzelpersonen können am JCP teilnehmen [Sch06 S.2]. 5 Kapitel 2: Einführung in die Java Mobile Edition 2.2 Spezielle Konfigurationen: CLDC und CDC Abhängig vom Anwendungsgebiet wird Java-ME in zwei Bereiche unterteilt, zum einen in einen Bereich für limitierte Geräte und zum anderen in einen Bereich für leistungsfähigere Geräte. Die Connected Limited Device Configuration (CLDC) [Su00b] wurde speziell für limitierte Geräte entwickelt. Bestandteil dieser Konfiguration ist die Kilobyte Virtual Machine (KVM), die eine Referenzimplementierung für die durch die CLDC definierte virtuelle Maschine darstellt. Bedingt durch den Einsatz auf Geräten mit langsamen Prozessoren und geringen Speicherkapazitäten implementiert die KVM nur eine Teilmenge der auf Desktop- und Serveranwendungen zugeschnittenen JVM. Als ergänzende Profile zu der CLDC existieren die Mobile Information Device Profile (MIDP). Eine vollständige Laufzeitumgebung für die limitierten Geräte setzt sich folglich aus der CLDC und den MIDP zusammen. Java-Programme zur Ausführung auf einem dieser Geräte werden als MIDlets bezeichnet [Br06 S. 34 ff.]. Im Bereich der leistungsfähigeren Geräte kann die Connected Device Configuration (CDC) zusammen mit den Foundation und Personal Profilen eingesetzt werden. Im Gegensatz zur CLDC setzt die CDC auf die JVM anstelle der KVM, da die Beachtung von Hardwarelimitationen in diesem Einsatzgebiet nicht zwingend notwendig ist. Für die CLDC gilt im Gegensatz zur CDC, dass nicht nur eine begrenzte Menge an verfügbaren Java-Klassenbibliotheken zur Verfügung stehen, sondern auch die Erstellung und Ausführung des Bytecodes bedingt durch den Einsatz der KVM gewissen Limitationen unterliegt. Diese Einschränkungen gegenüber der JVM und deren Auswirkungen auf die Sprache Java werden im weiteren Verlauf dieser Arbeit diskutiert. Als Grundlage für die Beschreibung der Einschränkungen wird im Folgenden zunächst die Architektur der JVM vorgestellt. 6 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition 3 Virtuelle Maschinen für die Java Mobile Edition 3.1 Architektur der Java Virtual Machine Eine Java Virtual Machine (JVM) wird benötigt, um in Java geschriebene Programme auf verschiedensten Plattformen lauffähig zu gestalten. Die Programmiersprache Java ist einer JVM dabei im Wesentlichen unbekannt. Diese arbeitet lediglich mit dem aus Java-Programmen erzeugten Bytecode. Der Bytecode muss einem bestimmten Format, dem Class-Format, entsprechen und wird zur Laufzeit von der virtuellen Maschine verifiziert und interpretiert. Die virtuelle Maschine vermittelt zwischen verschiedenen Schichten der Rechnerarchitektur. Im speziellen Fall der JVM findet eine Übersetzung des compilierten Bytecodes in den Maschinencode der jeweiligen Plattform statt. Dies ermöglicht es, einmal kompilierte Programme auf verschiedensten Plattformen lauffähig zu gestalten. Die JVM ist der Schlüssel für die Portabilität von Java. Sie übernimmt die betriebssystemspezifischen Abhängigkeiten und Unterschiede, so dass diese nicht in den Anwendungen berücksichtigt werden müssen. Notwendig hierfür ist eine JVMImplementierung für die jeweilige Plattform. Für alle gängigen Plattformen sind entsprechende Implementierungen vorhanden. Für Implementierungen der JVM existiert eine einheitliche Spezifikation [Li96]. Diese definiert grundlegende Charakteristika und Verantwortlichkeiten, die eine Implementierung umsetzen muss, und bietet in speziellen Bereichen Implementierungsspielräume. Ein Beispiel für einen solchen Spielraum ist die Implementierung eines Algorithmus zur Garbage Collection. Dieser ist in der Spezifikation nicht explizit vorgegeben. Im Folgenden wird eine detaillierte Beschreibung anhand der Spezifikation der JVM vorgenommen. Sie erfolgt anhand der in Abbildung 2.3 dargestellten konzeptionellen Architekturübersicht: Die Aufgaben der JVM werden angelehnt an [Wh02 Kap. 14] in unterstützende Aufgaben und laufzeitabhängige Aufgaben unterteilt. Die Übersicht beinhaltet ebenso Kennzahlen zu technischen Minimalanforderungen, beispielsweise der benötigten Mindestmenge an freiem Hauptspeicher. Anschließend ermöglicht sie Vergleiche zu alternativen Spezifikationen wie der KVM und der CVM. 7 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition Abb. 3.1: Architekturübersicht der JVM 3.1.1 Unterstützende Aufgaben der JVM Die unterstützenden Aufgaben sind in der Architekturübersicht zentral angeordnet. Jede Aufgabe stellt eine spezielle Funktion zur Laufzeit der JVM bereit. Class File-Format Das Class File-Format legt die Struktur des Bytecodes fest. Diese Struktur muss von Java-Compilern eingehalten werden. Wird die Struktur nicht eingehalten und der erzeugte Bytecode weicht von dem Class File-Format ab, so verhindert die JVM im Verifikationsprozess die Ausführung des Bytecodes. Der Fokus bei der Definition des Class File-Formats liegt in der Definition von Class Files als unabhängige Einheiten. Jedes Class File definiert einen eigenen KonstantenPool sowie Methoden und Exception-Tabellen. Dies ermöglicht eine dynamische Erweiterung von Anwendungen zur Laufzeit und erlaubt die Zusammensetzung einer Applikation aus mehreren unabhängigen Einheiten. Datentypen Analog zu der Programmiersprache Java unterscheidet die virtuelle Maschine zwischen zwei grundsätzlichen Datentypen: primitive Datentypen und Referenztypen. Primitive Datentypen sind innerhalb der JVM numerische Typen und Rücksprungadressen. Numerische Typen werden weiter unterteilt in Integraltypen und Fließkommatypen. Den Referenztypen sind hingegen Referenzen auf Objekte zuzuordnen. Innerhalb der virtuellen Maschine gelten dynamische Klasseninstanzen und Arrays als Objekt. Der Wert eines Referenztypen ist als Zeiger auf das Objekt zu verstehen, wobei ein Objekt 8 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition mehrere Zeiger aufweisen kann. Die virtuelle Maschine arbeitet bei Operationen auf Objekten nur mit den Referenztypen und nicht direkt auf den Objekten. Ein spezieller Wert eines Referenztypen ist der Wert null. Dieser gibt an, dass die Referenz auf kein Objekt verweist. Threads und Synchronisierung Die JVM unterstützt die gleichzeitige Ausführung mehrerer Threads. Jeder Thread führt eigenständigen Java Code aus und kann auf Objekten in einem für alle Threads gemeinsamen Speicherbereich arbeiten. Threads arbeiten abwechselnd mit Hilfe der Zuordnung von Zeitscheiben, wobei an einzelne Threads Prioritäten vergeben werden können. Sie können als Hintergrund-Threads markiert werden, um Dienstaktivitäten auf einem System durchzuführen. Die JVM kann für interne Zwecke ebenfalls eigene Hintergrund-Threads erzeugen, beispielsweise für den Garbage Collector. Durch die Verwendung von Threads ist das Ergebnis bestimmter Operationen abhängig vom Zeitpunkt der Ausführung, falls mehrere Threads eine Operation gleichzeitig durchführen und dabei auf die gleichen Objekte zugreifen. Dies führt in bestimmten Fällen zu einem nichtdeterministischen Verhalten. Um trotz gleichzeitiger Ausführung ein deterministisches Verhalten eines Programmes zu erhalten, unterstützt die JVM die Synchronisation von Ausführungsbereichen mit Hilfe des Monitorkonzepts. Ausführungsbereiche können so gekennzeichnet werden, dass nur ein Thread gleichzeitig diesen Bereich bearbeiten darf, indem der markierte Bereich für andere Threads gesperrt wird. Datenstrukturen zur Laufzeit der JVM Die JVM führt für jeden laufenden Thread einen Befehlszähler. Da ein Thread nur eine einzelne Methode zu einem Zeitpunkt ausführen kann, besitzt der Befehlszähler die Adresse der aktuell ausgeführten Instruktion. Zusätzlich zu dem eigenen Befehlszähler besitzt jeder Thread einen eigenen Stack. Erzeugt wird dieser Stack zum selben Zeitpunkt wie der zugehörige Thread. Der Stack bietet Platz für die einzelnen Frames der JVM. Durch die Verwendung von Frames für die einzelnen Methoden wird der Stack nicht direkt manipuliert. Die einzig gültigen Operationen für den Stack sind Operationen zum Ablegen und Herunterladen der auf dem Stack angeordneten Frames. 9 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition Ein Frame wird innerhalb der JVM für das Speichern von lokalen Variablen, Zwischenresultaten und Rückgabewerten von Methoden verwendet, sowie für dynamisches Linken und das Verteilen von Exceptions. Jeder Frame hat eine Menge lokaler Variablen und einen Operandenstack. Lokale Variablen werden in einem Array gespeichert, wobei die Länge eines Eintrags der jeweiligen Wortlänge der JVM Implementierung entspricht. So belegt eine lokale Variable immer genau eine Wortlänge im Speicher. Die Werte long und double werden als je zwei lokale Variablen gespeichert. Der Operandenstack wird für die Instruktionen der JVM benötigt. Eine Instruktion holt sich die benötigten Werte zur Berechnung von dem Stack und speichert das Ergebnis auf dem selbigen. Der Operandenstack wird ebenfalls benötigt, um Argumente an Methoden zu übergeben und die Rückgabewerte von Methoden zu speichern. Analog zu den lokalen Variablen gilt, dass ein Wert im Operandenstack eine Wortlänge im Speicher reserviert und long und double als je zwei Werte gespeichert werden. Da in der JVM für jeden Typen eigene Instruktionen vorhanden sind, dem int-Typen sind beispielsweise eigene Instruktionen zum addieren und multiplizieren zugeordnet, müssen die vom Operandenstack geladenen Werte passend zu der jeweiligen Instruktion sein. Um in diesem Bereich eine irreguläre Manipulation des Bytecodes zu verhindern, wird der Bytecode im Lebenszyklus der JVM vor der Ausführung verifiziert. Abb. 3.2: Datenstrukturen zur Laufzeit 10 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition Zu jedem Zeitpunkt ist immer nur ein Frame aktiv. Ein aktiver Frame wird auch als aktueller Frame und die dazugehörige Methode als aktuelle Methode bezeichnet. Ein Frame wird inaktiv, wenn die zugehörige Methode beendet ist oder sie eine andere Methode aufruft. Wird eine Methode beendet und hat sie einen Rückgabewert, so übergibt sie diesen an den Frame der aufrufenden Methode. Als weitere Datenstruktur zur Laufzeit verwaltet die JVM den Heap. Dieser wird von allen Threads gemeinsam genutzt. Im Heap wird Speicher für alle Instanzen und Arrays bereitgestellt. Abbildung 3.2 gibt einen Überblick über die JVM Datenstrukturen. Das Freigeben von Speicher wird durch ein automatisiertes Management übernommen, dem Garbage Collector. Dieser prüft die Instanzen und Objekte dahingehend, ob sie in mindestens einem der laufenden Threads erreichbar sind. Erreichbar bedeutet, dass in mindestens einem der Frames eines Threads eine Referenz auf das Objekt gehalten wird. Das Entfernen von Objekten aus dem Speicher erfolgt niemals durch einen expliziten Aufruf. Fehlerbehandlung Wenn eine Anwendung die semantischen Bedingungen der Java-Programmiersprache verletzt, signalisiert die JVM dies dem Programm durch das Werfen einer Exception. Dieses veranlasst einen sofortigen Wechsel des Programmablaufs. Wird die Exception in dem aktuellem Frame nicht abgefangen, so wird die Bearbeitung der Methode abgebrochen. Die lokalen Variablen und der Operandenstack des Frames werden gelöscht und der Frame vom Stack entfernt. Anschließend wird der Frame der aufrufenden Methode aktiviert und die Exception in dem Kontext dieses Frames erneut geworfen. Dieses Vorgehen wird wiederholt, bis die Exception in einem Frame abgefangen wird. Wird die Exception in keinem der Frames abgefangen, so wird der Thread beendet. Sicherheit Sicherheitsgefährdende Operationen werden in Java mit Hilfe des Security Managers kontrolliert. Beispiele hierfür sind Netzwerkzugriffe und Zugriffe auf Systemressourcen. Die Zugriffserteilung ist dabei abhängig von der jeweiligen Implementierung des Security Managers. Der Security Manager ist innerhalb der JVM ein Objekt, das für jede Zugriffsart eine Methode implementiert, die die Zugriffserteilung regelt. Die JVM unterbindet zur Laufzeit das Austauschen des beim Start der JVM geladenen Security Managers. 11 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition Weitere Sicherheitsaspekte sind in den Kernbibliotheken der Java-SE bzw. Java Enterprise-Laufzeitumgebungen vorhanden. 3.1.2 Lebenszyklus der JVM während der Ausführung Die JVM-Spezifikation beschreibt im Detail den Lebenszyklus der JVM während der Ausführung [Li96 Kap. 2]. Start der JVM Für den Start der JVM muss eine Klasse angegeben werden, die den Einstiegspunkt der Anwendung definiert. Ein Beispiel für einen solchen Einstiegspunkt ist die mainMethode. Beim Aufruf der Klasse kann eine Reihe von Parametern angegeben werden, die getrennt durch Leerzeichen als ein String Array zusammengefasst und an die mainMethode übergeben werden. Diese ist jedoch nicht der einzig mögliche Einstiegspunkt. Bei Java Applets wird die start-Methode als Einstiegspunkt verwendet. Laden und Nachladen von Klassen Für die Ausführung einer Anwendung benötigt die JVM binäre Repräsentationen der Klassen und Interfaces. Das binäre Format von Klassen und Interfaces wird als Class File-Format, das binäre Objekt als Class-Objekt bezeichnet. Der JVM Classloader und deren Unterklassen implementieren den Prozess, um die binären Daten zu finden und in die JVM zu laden. Die unterschiedlichen Unterklassen können verschiedene Strategien einsetzen, um die Klassen zu laden. Mögliche Strategien sind das frühzeitige Einladen von Klassen oder das gleichzeitige Laden von Gruppen ähnlicher Klassen. Die Spezifikation der JVM schreibt an diesem Punkt keinen speziellen Algorithmus vor. Laut Spezifikation ist der Classloader jedoch dafür verantwortlich, dass auftretende Fehler zu dem Zeitpunkt an die Anwendung weitergeleitet werden, an dem der tatsächliche Zugriff auf die verursachende Klasse erfolgt. Dies ist beispielsweise bei einem Algorithmus zu beachten, der ein vorzeitiges Laden von Klassen umsetzt. Der primäre Classloader der virtuellen Maschine unterstützt nicht das Nachladen von Klassen. Dies bedeutet, dass eine Klasse nur einmal während des Lebenszyklus der JVM eingeladen wird. Wird eine Klasse mit einer neueren Version ersetzt, tritt die Änderung erst bei dem Neustart der JVM in Kraft. Dieses Verhalten gründet auf der Tatsache, dass die Java Kernklassen nur von dem primären Classloader geladen werden dürfen und das Austauschen der Kernklassen zur Laufzeit als Sicherheitsrisiko ein12 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition gestuft wird. Durch die Implementierung eines angepassten Classloader ist es möglich, dieses Verhalten zu ändern und Klassen dynamisch im Lebenszyklus der JVM nachzuladen. Linking: Verifikation, Vorbereitung und Auflösung Linking bedeutet, dass das geladene Class-Objekt in den laufenden Betrieb der JVM zur Ausführung integriert wird. Dieser Prozess setzt das Laden der Klassen voraus und wird in drei aufeinanderfolgende Aktivitäten unterteilt: Verifikation, Vorbereitung und Auflösen von symbolischen Referenzen. Die Verifikation überprüft aus Sicherheitsgründen die Bytecodestruktur der geladenen Klasse. Es wird beispielsweise geprüft, ob jede Bytecodeinstruktion einen im Sinne der JVM-Spezifikation gültigen Operationscode aufweist. Ebenfalls werden die Methodensignaturen auf Gültigkeit geprüft und die Einhaltung des Java-Typsystems verifiziert. Bei der Vorbereitung erfolgt die Allokation von Speicher für statischen Speicher und für von der JVM intern verwendete Datenstrukturen. Zu diesem Zeitpunkt werden die statischen Variablen einer Klasse mit ihren Standardwerten initialisiert. Zusätzliche interne Datenstrukturen der JVM können aus Effizienzgründen eingesetzt werden. Zum Beispiel kann eine Tabelle für Methodennamen als Suchindex zur Verfügung gestellt werden, um beim späteren Aufruf der Methoden eine Suche innerhalb der Vererbungshierarchie effizienter zu gestalten. Eine Klasse kann Methoden und Variablen anderer Klassen und Schnittstellen symbolisch referenzieren. Für die Verwendung dieser symbolischen Referenz innerhalb der virtuellen Maschine muss die Referenz aufgelöst werden. Sie wird hierbei auf Korrektheit überprüft und zu einer direkten Referenz aufgelöst. Das Auflösen von symbolischen Referenzen kann ein Laden weiterer Klassen auslösen. Die Spezifikation lässt Spielräume für Implementierungen, die festlegen zu welchem Zeitpunkt der Prozess des Linkens ausgeführt wird. Aus Effizienzgründen können alle symbolischen Referenzen und die dazu gehörenden Klassen beim Start der JVM geladen werden. Mehr Flexibilität verspricht dagegen die Lazy Resolution, bei der symbolische Referenzen erst bei Bedarf, d. h. erst während der Ausführung der Anwendung, aufgelöst werden. Dies beansprucht jedoch zusätzliche Ressourcen. 13 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition Initialisierung Der Prozess der Initialisierung wird angestoßen, wenn eine Klasse das erste Mal aktiv verwendet wird. Unter aktiver Verwendung versteht die Spezifikation das Aufrufen einer in der Klasse deklarierten Methode, das Aufrufen des Konstruktors oder das Aufrufen einer nicht konstanten Membervariablen der Klasse. Andere Verwendungen der Klasse, wie beispielsweise der Zugriff auf Konstanten der Klasse, werden als passiv bezeichnet und lösen keine Initialisierung aus. Bei der Initialisierung werden Speicherbereiche für statische Blöcke und Membervariablen der verwendeten Klasse bereitgestellt. Sie wird durchgeführt, um die Klasse beim ersten Zugriff in einen konsistenten Zustand zu bringen. Erzeugung neuer Instanzen Instanzen einer Klasse können explizit oder implizit erstellt werden. Das Aufrufen der Methode newInstance aus der Klasse Class ist ein Beispiel für das explizite Erzeugen einer Instanz einer Klasse, auf deren Objekt diese Methode ausgeführt wird. Die implizite Erzeugung von Objekten erfolgt beispielsweise durch das Zusammenfügen von Zeichenketten. Die Erzeugung neuer Instanzen beinhaltet die Bereitstellung von Speicher für das neue Objekt. Hierbei wird für alle deklarierten Membervariablen der Klasse und alle Oberklassen Speicher alloziert. Anschließend werden die Variablen mit ihren Standardwerten initialisiert. Zum Abschluss wird der Konstruktor der Klasse ausgeführt, und die Referenz auf das neue Objekt zurückgegeben. Freigabe von Ressourcen und Beenden der JVM Mit Hilfe eines Finalize-Prozesses beschreibt die Spezifikation der JVM eine Möglichkeit, Ressourcen automatisch beim Beenden freizugeben, die nicht durch den Garbage Collector oder andere Hintergrunddienste freigegeben werden können. Mögliche Ressourcen in diesem Bereich sind Datenbankverbindungen oder Netzwerkverbindungen. Diese werden nicht zwingend bei dem Entfernen eines Objekts aus dem Speicher automatisch freigegeben. Die Freigabe kann durch expliziten Aufruf der finalize-Methode oder implizit bei der Beendigung der JVM erfolgen. Die dabei durchgeführten Operationen müssen in beiden Fällen in der finalize-Methode innerhalb der Anwendung implementiert werden. Die Spezifikation beschreibt den Finalize-Prozess 14 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition als optional zu einer JVM-Implementierung und schreibt keinen detaillierten Mechanismus vor, der diesen Prozess auf Seiten der JVM umsetzt. Die Ausführung der JVM wird beendet, wenn alle in ihr laufenden Threads beendet sind. Alternativ erfolgt eine Beendigung, wenn ein laufender Thread die exit-Methode der Klasse Runtime bzw. System aufruft und diese Operation durch den Security Manager zugelassen wird. 3.2 Die Kilobyte Virtual Machine Die KVM ist eine Implementierung einer innerhalb der CLDC definierten virtuellen Maschine. Die KVM bietet die Grundlage für die Jave Micro Edition im Bereich von Mobiltelefonen, Pagern und Personal Organizern. Zusammen mit grundlegenden Klassenbibliotheken bildet die KVM die vom Java Community Process spezifizierte Konfiguration CLDC. Die Entwicklung der KVM wurde im Wesentlichen durch die technische Herausforderung getrieben, den benötigten Speicher während der Programmausführung und die Anforderungen an die Prozessorleistung zu minimieren. Eine weitere Anforderung ist es, Komponenten der virtuellen Maschine für verschiedene Einsatzgebiete flexibel zu gestalten. Unter den gegebenen Einschränkungen der Hardware ermöglicht die KVM die Umsetzung der zentralen Gesichtspunkte der Programmiersprache Java. Die geringen Anforderungen der KVM spiegeln sich in ihrem Namen wieder. Er deutet darauf hin, dass der Speicherverbrauch in Kilobytes und nicht wie bei Desktopsystemen üblich in Megabytes angegeben wird. Die tatsächliche Speicheranforderung wird durch die jeweilige Implementierung einer KVM und der auf der KVM aufbauenden Konfiguration determiniert [Sch06 S. 14]. 3.2.1 Hardwareanforderungen der KVM Die Speicheranforderung dieser Konfiguration mit einer typischen Implementierung der KVM beträgt 256 Kilobytes. Es sind aber Implementierungen möglich, die mit 128 Kilobyte Speicher lauffähig sind. Die virtuelle Maschine nimmt dabei nur 40-80 Kilobyte Speicher ein. Die genaue Menge ist abhängig von der Implementierung und der Zielplattform. Weiterer Speicherplatz wird für das Einladen der durch die CLDC spezifizierten Klassenbibliotheken sowie für die Klassenbibliotheken des verwendeten 15 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition Profils benötigt. Die restliche Speichermenge wird für den Heap Speicher der laufenden Anwendungen verwendet. Das Verhältnis von flüchtigem Speicher zu nicht-flüchtigem Speicher ist ebenfalls abhängig von der Implementierung. Unterstützt die Implementierung das Prelinken von Systemklassen wird weniger Speicher benötigt, da Systemklassen und eventuell Anwendungen in den nicht-flüchtigen Speicher der Geräte eingeladen werden können [Kn03 Kap. 1]. Die Rolle der KVM in einem Gerät hängt zudem von der Integration in das Betriebssystem ab. Es ist beispielsweise möglich, dass Betriebssystemfunktionen ebenfalls in Java auf Basis der KVM programmiert werden. In den meisten Fällen setzt die KVM jedoch auf das native Betriebssystem auf. Dies ermöglicht dynamische und sichere Java Anwendungen auf dem Gerät. Sun Microsystem stellt eine Referenzimplementierung der KVM bereit. Diese ist in der Sprache C programmiert. Dadurch ist es möglich, die KVM auf jeder Plattform bereit zu stellen, für die ein C-Compiler existiert. Bei der Adaption auf eine neue Plattform muss nur ein Teil der KVM-Funktionen angepasst werden. Hierzu gehören unter anderem Initialisierungen, Heap-Allokationen und Event-Handlings. Die Referenzimplementierung ist ausgelegt auf 32-Bit Systeme, sie ist gemäß der Spezifikation jedoch auch auf 16-Bit Systemen lauffähig [Su00a S.29]. 3.2.2 Einschränkungen gegenüber der Java Virtual Machine Die KVM unterscheidet sich im Vergleich zur JVM im Wesentlichen durch Einschränkungen. Außer den in den CLDC-Spezifikationen 1.0 und 1.1 genannten Einschränkungen besitzt sie alle Eigenschaften der JVM. In Abbildung 3.3 sind die Einschränkungen zur Übersicht durch die Schraffur speziell gekennzeichnet. 16 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition Start der VM Laden von Klassen Verifikation und Linken Sicherheit Threads Interne Datenstrukturen Fehlerbehandlung Class File Format Unterstützung Datenypen Freigabe und Beenden Erzeugung Instanzen Initialisierung Speicheranforderung an Geräte: CLDC 1.0 160 kB | CLDC 1.1 192 kB Abb. 3.3: Architekturübersicht und Einschränkungen der KVM Verifikation von Bytecode Eine der CLDC konforme virtuelle Maschine muss in der Lage sein, nicht dem Class File-Format entsprechende Bytecodedateien direkt nach dem Laden zurückzuweisen. Der von der JVM spezifizierte Prozess zur Bytecode-Verfikation ist für CLDCEndgeräte ungeeignet, da zur Laufzeit eine zu große Menge an Speicherkapazität in Anspruch genommen wird. Daher spezifiziert die CLDC einen hinsichtlich des Speicherverbrauchs effizienteren Prozess der Verifikation. Die Bytecode-Verifikation der KVM ist in zwei Phasen aufgeteilt, die Pre-Verifikation und die Laufzeit-Verifikation. Die Pre-Verifikation ist losgelöst von der Laufzeit einer Anwendung und wird bereits zur Buildtime durchgeführt. Bei ihr erfolgt das Inlining und das Austauschen spezieller Bytecode Operationen. Ein Class File erhält eine spezielle Kennzeichnung, wenn es den Prozess der Pre-Verification durchlaufen hat. Die Kennzeichnung erfolgt in Form spezifizierter Stack Map-Attribute. Diese speziellen Attribute werden bei der JVM-Bytecode-Verifikation ignoriert, so dass preverifizierte Class Files hinsichtlich der Verwendung innerhalb der JVM aufwärts kompatibel sind. Die Laufzeit-Verifikation sichert die Typsicherheit bei Ausführung des Bytecodes und verhindert so unerlaubte Zugriffe auf Speicherbereiche. Vor der Ausführung der Laufzeit-Verifikation werden die Attribute der Pre-Verifikation kontrolliert, Class Files mit fehlenden oder fehlerhaften Attributen werden zurückgewiesen und nicht in die virtuelle Maschine geladen. 17 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition Laden von Klassen Die KVM bietet keine Möglichkeit den Classloader zu erweitern oder zu ersetzen. Das Laden von Klassen erfolgt ausschließlich durch in der KVM implementierte Classloader. So wird garantiert, dass das Austauschen der Java-Sicherheitspakete zur Laufzeit nicht möglich ist. Dieses Vorgehen ist notwendig, da nicht das vollständige Java-Sicherheitsmodell der JVM umgesetzt wird. Bedingt durch die ausschließliche Verwendung des Standard-Classloaders ist ein dynamisches Nachladen von Klassen nicht möglich. Garbage Collector Garbage Collection spielt im Bereich der KVM eine wichtige Rolle. Aufgrund der begrenzten Speicherkapazität als auch der geringen Prozessorleistungen der Endgeräte ist es notwendig, dass der Garbage Collector möglichst viel Speicher bei gleichzeitiger Minimierung der dafür notwendigen Prozessorzyklen freigibt. Der KVM-Garbage Collector ist auf geringe Heap-Größen ausgerichtet und innerhalb der virtuellen Maschine vollständig implementiert. Er ist modular in die KVM integriert, so dass eine Anpassung und ein Austausch für verschiedene Implementierungen möglich sind. Dies ist notwendig, da die Effizienz eines Garbage Collectors zu einem erheblichen Anteil von der Zielplattform abhängt und dort Schwankungen unterliegt. Weak References Die Verwendung von schwachen Referenzen erlaubt es, weiterhin eine Referenz auf ein Objekt zu halten, dieses aber gleichzeitig für den Garbage Collector freizugeben. Zur Vereinfachung des Garbage Collectors werden schwache Referenzen nicht von der KVM unterstützt. Freigabe von Ressourcen Die Möglichkeit, eine Freigabe von Ressourcen mit Hilfe einer Implementierung der finalize-Methode an die virtuelle Maschine zu delegieren, ist bei der KVM nicht vorhanden. Dies dient der Vereinfachung des Garbage Collectors. Multithreading Die KVM unterstützt keine eventuellen Multithreading-Möglichkeiten der nativen Umgebung. Im Wesentlichen ist dies darin begründet, dass ein Großteil der KVM18 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition Zielgeräte keine Multiprozessorsystem sind. Der Vorteil beim Vernachlässigen der nativen Multithreading-Möglichkeiten ist, dass die Portierung der KVM auf verschiedene Systeme vereinfacht wird. Beim Scheduling von Threads implementiert die KVM ein pragmatisches Verfahren. Der aktuelle Thread gibt jeweils nach einer bestimmten Anzahl von ausgeführten Instruktionen die Kontrolle an den nächsten zur Ausführung geplanten Thread ab. Zusätzlich unterstützt die KVM nicht das Gruppieren von Threads sowie das Markieren von Threads als Hintergrunddienst. Fließkomma-Arithmetik Die KVM stellt keine Instruktionen zur Fließkomma-Arithmetik und keine entsprechenden Datentypen bereit. Dies ermöglicht das Einsparen einer Menge von Bytecode-Instruktionen, die zur Berechnung von Fließkommazahlen notwendig wären. Durch das Auslassen dieser Bytecode-Instruktionen wird die Implementierung der JVM vereinfacht und damit einhergehend die benötigte Speichermenge reduziert. Begründet wird dieses Auslassen durch die fehlende Hardware-Unterstützung von FließkommaOperationen bei der Vielzahl der CLDC konformen Endgeräte. Als Konsequenz sind die Java-Schlüsselwörter float und double im Kontext einer CLDC 1.0 konformen KVM nicht gültig und können in den Anwendungen nicht verwendet werden. Reflection Mit Hilfe der Reflection ist es einer Anwendung möglich, ihre eigenen Metadaten zur Laufzeit abzufragen. Dies bedeutet, dass sie in der virtuellen Maschine vorhandene Klassen und deren Membervariablen und Methoden inspizieren kann. Die Spezifikation von JavaBeans baut beispielsweise auf der Verwendung von Reflection auf. Dadurch, dass die KVM Reflection nicht ermöglicht, ist weder die Verwendung von JavaBeans und Remote Method Invocation noch das Serialisieren von Objekten möglich. Fehlerbehandlung Das Behandeln von Exceptions entspricht im Wesentlichen der JVM-Spezifikation. Lediglich die Anzahl der von der KVM verwendeten Error-Typen ist limitiert. Ein Error ist eine spezielle Art einer Exception. Er kann im Gegensatz zu einer Exception nicht abgefangen werden und führt zur Beendigung der ausführenden Anwendung. Dieses 19 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition Verfahren beim Auftreten eines Errors ist aufwendig zu implementieren und kostspielig zur Laufzeit. Daher ist die Anzahl der von der KVM erkannten Errors limitiert. Unterstützung nativer Code Die KVM unterstützt im Gegensatz zur JVM nicht das Java Native Interface (JNI). Um nativen Code aufrufen zu können, muss dieser direkt zur Compilezeit mit dem Code der virtuellen Maschine verlinkt werden. Lookup-Tabellen für native Methoden müssen im Build-Prozess erstellt werden, um native Methoden aufrufen zu können [To02 S. 39 ff.]. Sicherheit Die Begrenzungen der Speicherkapazitäten erlauben es der CLDC nicht, das vollständige Sicherheitskonzept der JVM und die damit verbundenen Java- Kernbibliotheken zu übernehmen. Das Sicherheitskonzept der CLDC setzt auf eine minimale Sicherheitsschicht innerhalb der virtuellen Maschine und auf zusätzliche Sicherheitsmechanismen auf der Ebene der Anwendungen. Sicherheitsmechanismen auf Ebene der virtuellen Maschine sind lediglich die Verifikation des Bytecodes sowie die Restriktionen beim Laden von Klassen. Zusätzliche Sicherheit bietet der Verzicht auf die Einbindung von nativem Code zur Laufzeit. Diese Mechanismen garantieren, dass die Anwendungen innerhalb einer geschützten Umgebung ablaufen und keine Möglichkeit haben, das unterliegende Betriebssystem zu kompromittieren. Auswirkungen der Einschränkungen auf die Programmiersprache Java Neben der Reduzierung der benötigten Speichermenge haben die Einschränkungen den Effekt, dass eine KVM gegenüber einer vollständigen JVM leichter implementiert werden kann. Der Nachteil ist dagegen, dass eine KVM nicht unbedingt den Bytecode verarbeiten kann, den ein Standard-Java-Compiler erzeugt. Dadurch sind einige Schlüsselwörter der Java-Programmiersprache im Kontext der KVM nicht gültig und deren Verwendung muss bei der Entwicklung von Anwendungen für die KVM unterbunden werden. Eine Möglichkeit dies zu Kontrollieren wäre die Erzeugung eines speziellen Compilers, der im Sinne der KVM ungültigen Quelltext nicht kompiliert. In der Praxis wird diese Prüfung in den Prozess der Pre-Verifikation des Bytecodes ausgelagert. Auf der KVM nicht ausführbare Class-Dateien, bedingt durch nicht unterstützte Java-Features, werden nicht verifiziert. Dies verhindert eine mögliche Ausführung innerhalb der KVM, da die 20 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition Class Dateien bei der Laufzeit-Verifikation aufgrund fehlender Attribute nicht akzeptiert werden. 3.2.3 Aufgehobene Einschränkungen der CLDC 1.1 gegenüber der CLDC 1.0 Die CLDC 1.1 [Su03] hebt einige Einschränkungen im Sprachumfang und der Fähigkeiten der virtuellen Maschine auf, erfordert aber auch mehr Speicher im ROM. Diese Spezifikation trägt der technischen Entwicklung und der damit verbundenen teilweisen Entschärfung von Limitationen im Bereich der Hardware Rechnung. Fließkomma-Arithmetik Die CLDC Version 1.1 bietet explizite Unterstützung für die Fließkomma-Datentypen float und double, da eine Vielzahl neuer Endgeräte entsprechende Hardwarevoraussetzungen für die Verarbeitung von Fließkommazahlen mit sich bringt. Dies erhöht den Speicherbedarf, da zusätzliche Bytecodeoperationen geladen und deren Umsetzung in Mikroprozessorcode von der KVM zusätzlich implementiert werden muss. Zudem sind deutliche Performanzeinbußen möglich, falls die Hardware Fließkommaoperationen nicht unterstützt und diese innerhalb der KVM emuliert werden müssen [Sch06 S. 19]. Weak References Die Verwendung schwacher Referenzen ist in der neuen Version der CLDC erlaubt. Dies erhöht allerdings die Anforderungen an die verwendete Implementierung des Garage Collectors. Neben den aufgehobenen Einschränkungen im Bereich der virtuellen Maschine sind zusätzliche Klassenbibliotheken eine wesentliche Neuerung gegenüber der alten Spezifikation. 3.2.4 Spezielle Erweiterungen für die KVM Java Code Compact (JCC) Das JCC ermöglicht es, Java Klassen direkt in die virtuelle Maschine zu verlinken. Die Java-Klassen werden dabei kombiniert, anschließend wird aus ihnen eine C-Datei erzeugt. Diese kann compiliert und mit der virtuellen Maschine verlinkt werden. Dadurch bietet JCC ein alternatives Modell, um Programme zu verlinken und Symbole aufzulösen. Jedoch ist dieses Modell weniger flexibel gegenüber dem Java-Classloading21 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition Mechanismus. Es ist jedoch hilfreich, um die Speicheranforderungen der virtuellen Maschine zu reduzieren. Java Application Manager (JAM) Der JAM bietet eine Schnittstelle zwischen dem Betriebssystem eines Geräts und der virtuellen Maschine. Er verwendet das Generic Connection Framework um JARDateien über Netzwerkprotokolle herunterzuladen und dem Endgerät zur Verfügung zu stellen. Zum Starten der Anwendung identifiziert JAM die Hauptklasse aus dem Inhalt der JAR-Datei mit Hilfe der zugeordneten Beschreibungsdatei. Diese identifizierte Hauptklasse wird beim Start der KVM als Parameter übergeben. 3.3 Java Card Virtual Machine (CVM) Die Java-CVM [Su05] ermöglicht die Entwicklung von Anwendungen für Smart Cards und Geräte mit ähnlich eingeschränkten Hardwareressourcen. Aufgrund der erheblichen Einschränkungen im Hardwarebereich wird nur eine geringe Teilmenge der Eigenschaften der Java-Plattform umgesetzt. Anwendungen für die CVM werden mit dem Standard-Java-Compiler erstellt. Dieser Bytecode im Class File-Format wird anschließend in das spezielle CVM CAP-Format umgewandelt. Bei der Erstellung der Anwendungen, die im Bereich der CVM als Applets bezeichnet werden, sind die in Abbildung 3.5 grafisch angedeuteten und im Folgenden aufgelisteten Einschränkungen zu beachten. Abb. 3.5: Architekturübersicht der CVM Die CVM bietet keine Unterstützung für die gleichzeitige Ausführung mehrerer Threads, ein Applet besteht immer genau aus einem Thread. Im Bereich des Sicher22 Kapitel 3: Virtuelle Maschinen für die Java Mobile Edition heitsmanagement gilt die Einschränkung, dass kein Security Manager unterstützt wird, alle Sicherheitsrichtlinien sind direkt in der CVM verankert. Analog zu der KVM wird ebenfalls das Freigeben von Ressourcen mit Hilfe der finalize-Methode nicht unterstützt. Ebenso ist das dynamische Laden von Klassen nicht möglich. Die CVM unterscheidet bei den Datentypen ebenfalls zwischen primitiven Datentypen und Referenzdatentypen. Bei den primitiven Datentypen werden allerdings nicht die speicherintensiven Typen long, char, double und float abgebildet. Der ExceptionMechnismus der Java-Plattform wird unterstützt, allerdings ist die verfügbare Menge an Exception- und Errortypen stark eingegrenzt. Die Datenstrukturen zur Laufzeit gleichen in etwa denen der JVM, allerdings gibt es aufgrund der fehlenden Thread-Unterstützung nur einen einzigen Stack. Ein zusätzlicher Unterschied zur JVM ist dadurch gegeben, dass Garbage Collection auf dem Heap nicht zwingend vorgeschrieben ist. 23 Kapitel 4: Zusammenfassung und Ausblick 4 Zusammenfassung und Ausblick Im Rahmen dieser Ausarbeitung wurden neben einer einleitenden Übersicht die wesentlichen Unterschiede vorhandener virtueller Maschinen im Bereich der Java Mobile Edition ausgearbeitet. Ausgehend von einer detaillierten Beschreibung der als Referenzarchitektur geltenden JVM-Spezifikationen wurden die aufgrund bestehender Harwarerestriktionen notwendigen Einschränkungen der KVM und CVM herausgearbeitet, wobei der Schwerpunkt deutlich auf die Beschreibung der KVM gelegt wurde. Als allgemeine Kritik an der Java Mobile Edition ist das Fehlen einer einheitlichen, durchgängigen Spezifikation zu nennen. Stattdessen existieren mehrere, teilweise aufeinander aufbauende Spezifikationen, aber auch teilweise sich gegenseitig ausschließende Spezifikationen. Dies ist als Konsequenz der gewünschten Modularität und der daraus resultierenden Aufteilung der Laufzeitumgebung in auf Geräteklassen angepasste Konfigurationen und Profile zu sehen. Ein spezieller Nachteil der KVM ist, dass keine vollständige Kompatibilität zu Standard-Java-Anwendungen besteht. Die Abwärtskompatibilität kann zwar durch PreVerifikation geprüft werden, allerdings ist eine Aufwärtskompatibilität nicht immer gegeben, da die CLDC-Bibliotheken verwendet, in der Java-Laufzeitumgebung nicht vorhanden sind. Kritisch ist weiterhin zu sehen, dass ein Großteil der bewährten und umfassenden Sicherheitsfeatures der JVM in der KVM nicht übernommen werden konnten. Speziell bei mobilen Endgeräten ist die Sicherheit ein kritischer Faktor. Hier bleibt abzuwarten, inwiefern sich das eingeschränkte Sicherheitskonzept im Verlauf der Zeit bewährt. Vorteilig ist bei der KVM durch die grundlegende Neuentwicklung, dass bisher in der JVM umstrittene, jedoch aus Kombatibilitätsgründen weiterhin vorhandene Features entfernt wurden. Sie bietet daher im Gegensatz zur JVM eine effizientere Performanz durch schlankere Strukturen. Aufgrund dessen ist die Möglichkeit gegeben, dass sich die KVM als Standard für nahezu alle mobilen Endgeräte entwickeln kann, da sich ein Großteil der aktuellen Einschränkungen der nicht wesentlich auf die Möglichkeiten der Java-Programmiersprache auswirkt. Die weiterentwickelte und auf die gestiegenen Hardwarepotenziale angepasste CLDC 1.1 hebt mit der Unterstützung für Fließkommazahlen eine der gravierendsten Einschränkungen auf. 24 Kapitel 4: Zusammenfassung und Ausblick Weiterhin bleibt abzuwarten, welche alternativen Implementierungen einer CLDC konformen virtuellen Maschine entstehen und welche Einschränkungen, aber auch Vorteile diese Implementierungen gegenüber der JVM und KVM mit sich bringen. Tendenziell wird es aufgrund weiterer technischer Fortschritte eine Entwicklung dahingehend geben, dass eine Vielzahl der mobilen Endgeräte nicht mehr den momentanen Hardwarerestriktionen unterliegen und so eher der CDC zuzuordnen sind. Modularität stellt sicher, dass durch Kombination mit erweiterten Profilen die Merkmale leistungsstärkeren Systemen ausgenutzt werden können und der Einsatz der KVM auch auf neu entwickelten Geräten weiterhin sinnvoll ist. Die CVM als Nischenprodukt im Bereich der Smart Cards besitzt den Vorteil, dass die auf sie abgestimmten Programme auf der Vielzahl der unterschiedlichen Kartensysteme lauffähig sind. Deshalb besteht das Potenzial, dass sich die CVM als Standard für die Entwicklung von Smart Card-Anwendungen etabliert. 25 Literaturverzeichnis Literaturverzeichnis [Br06] Ulrich Breymann, Heiko Mosemann: Java ME – Anwendungsentwicklung für Handys, PDA und Co., Hanser Fachbuchverlag, 2006. [Kn03] Jonathan Knudsen: Wireless Java Developing with J2ME, 2nd. ed., Apress, 2003. [Li96] Tim Lindholm, Frank Yellin: The Java Virtual Machine Specification, Addison-Wesley-Longman, 1996. [Sch06] Klaus-Dieter Schmatz: Java Micro Edition – Entwicklung mobiler JavaMeAnwendugen mit CLDC und MIDP, 2nd. ed., dpunkt.verlag, 2006. [Su00a] Sun Microsystems:J2ME Building Blocks for Mobile Devices, White Paper, 2000. [Su00b] Sun Microsystems: Connected, Limited Device Configuration Specification 1.0a, 2000 [Su03] Sun Microsystems: Connected, Limited Device Configuration Specification 1.1, 2003. [Su05] Sun Microsystems: CVM Specification, Version 2.2.2, 2005. [To02] Kim Topley: J2ME in a Nutshell, O'Reilly, 2002. [Wh02] James White, David Hemphill: Java in Small Things, Manning, 2002. 26 Hinweis: Die unten angeführte Erklärung wird nur bei Bachelor- oder Diplomarbeiten benötigt, nicht jedoch bei Seminarausarbeitungen. Bei Bachelorarbeiten ist darauf zu achten, dass das Wort „Diplomhausarbeit“ durch „BachelorAbschlussarbeit“ ersetzt wird. Ich versichere hiermit, dass ich meine Diplomhausarbeit <Titel der Arbeit> selbstständig und ohne fremde Hilfe angefertigt habe, und dass ich alle von anderen Autoren wörtlich übernommenen Stellen wie auch die sich an die Gedankengänge anderer Autoren eng anlegenden Ausführungen meiner Arbeit besonders gekennzeichnet und die Quellen zitiert habe. Münster, __________ _____________________________