2. Grundlagen von Java
In diesem Kapitel werden nach einer kurzen Ausführung zur Entwicklungsgeschichte
von Java die wichtigsten Eigenschaften von Java vorgestellt. Genauere Informationen
zur Entwicklung von Java finden sich auf den Java-Seiten
von Sun Microsystems.
2.1 Historisches
Die Entwicklung von Java begann, als Sun
Microsystems 1990 ein Team von sechs Softwareentwicklern zusammenstellte,
das eine Programmiersprache für Geräte der Unterhaltungselektronik,
wie Videorecorder und Settop-Boxen, entwickeln sollte. Damals dachte man
an Programme für das interaktive Fernsehen. Wichtigster Punkt, den
das sogenannte "Green Project" bei der Entwicklung beachten mußte,
war dabei die Portabilität der Programmiersprache, die mit dieser
Sprache geschriebenen Programme sollten also hardwareunabhängig sein.
Um nicht wieder eine völlig neue Programmiersprache zu entwickeln,
die alle Softwareentwickler erst neu erlernen müßten, wurde
"Oak", wie die Sprache zunächst genannt wurde, stark an C++ angelehnt.
Der Markt für das interaktive Fernsehen wuchs jedoch nicht so
schnell wie erwartet, jedoch übertraf die Entwicklung des Internet
durch die Einführung des World Wide Web alle Erwartungen. So wurden
1994 alle Anstrengungen von "First Person", eine Sun-Tochter, die aus dem
Green Project hervorging, in die Entwicklung eines Programmiersystems für
Online-Multimedia-Anwendungen gesetzt. 1995 präsentierte Sun das fertige
Ergebnis mit dem Namen "Java" der Öffentlichkeit. Gleichzeitig wurde
ein Softwareentwicklungssystem, das JDK
(Java Development Kit) und ein WWW-Browser mit dem Namen "HotJava",
der Java-Programme ausführen kann, vorgestellt.
Die Resonanz in den Fachkreisen und der Öffentlichkeit war sehr
groß. Kurz nach der Präsentation von Java lizenzierten viele
namhafte Soft- und Hardwarehersteller Java, darunter Netscape,
IBM und Microsoft.
Seither ist der Boom ungebrochen und mit der Vorstellung des JDK
1.2 Anfang 1998 ist bestimmt noch nicht der letzte Punkt erreicht.
2.2 Eigenschaften von Java
Die Programmiersprache Java besitzt einige Eigenschaften, die sie von anderen
Programmiersprachen abhebt. Im folgenden wird auf die wichtigsten dieser
Eigenschaften näher eingegangen.
2.2.1 Java als Programmiersprache für verteilte
Applikationen
Eine der wichtigsten Eigenschaften von Java ist, daß es mit Java
möglich ist, verteilte Applikationen zu erzeugen. Java-Programme können
dabei aus mehreren Teilen bestehen, die sich in einem Netzwerk auf verschiedenen
Rechnern befinden können. Auch die Daten müssen nicht aus der
gleichen Quelle wie das Programm stammen und können sich auf unterschiedlichen
Rechnern befinden. Durch diese Eigenschaft ist Java in idealer Weise dazu
geeignet, um für Applikationen im Internet eingesetzt zu werden.
2.2.2 Plattformunabhängigkeit
Bevor ein Java-Programm ausgeführt werden kann, wird der Quelltext
kompiliert, wobei der sogenannte Bytecode entsteht. Im folgenden
Beispiel, das aus BACK (1996)
entnommen wurde, ist ein kleines Java-Programm mit dazugehörigem Bytecode
dargestellt:
class Loop {
static public void main (String args[])
{
int i;
for (i = 0; i < 10; i++)
System.out.println(i);
// Ausgabe der Zahlen 0 bis 9 auf die Console
}
}
---------------------------------------
Compiled from loop.java |
|
class Loop extends java.lang.Object { |
|
public static void main(java.lang.String []); |
|
|
|
public Loop(); |
|
Method void main(java.lang.String []) |
|
0 iconst_0 |
// Lade 0 auf Stack |
1 istore_1 |
// Lade 0 in Variable <1> (i) |
2 goto 15 |
|
5 getstatic #6 <Field java.lang.System.out Ljava/io/PrintStream;> |
// Laedt Adresse des Print-Streams |
8 iload_1 |
// Lade Variable <1> auf den Stack |
9 invokevirtual #5 <Method java.io.PrintStream.println(I)V> |
// die aufgerufene Methode invalidiert den Stack vor ihrer Rückkehr |
12 iinc 1 1 |
// i++ |
15 iload_1 |
// Lade Variable <1> auf den Stack |
16 bipush 10 |
// 10 auf den Stack |
18 if_icmplt 5 |
// if (I<10) goto 5 |
21 return |
// Rückkehr in Objekt, das die Message geschickt hat |
|
|
Method Loop() |
|
0 aload_0 |
|
1 invokenonvirtual #7 <Method java.lang.Object.<init>()V> |
// Lade Objektreferenz_<0> auf den Stack |
4 return |
|
Der aus der Compilierung entstandene Bytecode stellt das ausführbare
Java-Programm dar. Dieser Bytecode wird bei der Ausführung von der
Java Virtual Machine (JVM) interpretiert. Somit sind also Java-Programme
auf allen Systemen ausführbar, für die eine Java Virtual Machine
existiert, zum Beispiel als Teil eines WWW-Browsers. Die Java Virtual Machine
stellt dem Java-Programm ein komplettes virtuelles Computersystem zur Verfügung.
Sie übernimmt dann durch die Interpretation des Bytecodes die Umsetzung
des Bytecodes in Maschinencode.
Vorteile der Plattformunabhängigkeit von Java-Programmen sind
unter anderem:
-
Kostspielige Portierungen von Software entfallen
-
Ein Programm ist sofort auf vielen Plattformen verfügbar
-
Da die Software nicht portiert werden muß, sind viele Fehlerquellen
ausgeschlossen
2.2.3 Objektorientierung
Java ist eine objektorientierte Programmiersprache. In Java wurden mit
einem Klassenkonzept, Vererbung, Polymorphismus und dynamisches Binden
wichtige Konzepte der objektorientierten Programmierung realisiert. Aus
der Objektorientierung resultieren verschiedene Vorteile, wie die Erweiterbarkeit
und die Wiederverwendbarkeit von in Java geschriebenen Programmen. Der
Bereich der Objektorientierung kann und soll allerdings im Rahmen dieser
Seminararbeit nur angesprochen werden.
2.2.4 Performance
Da Java-Programme zunächst kompiliert werden, wobei der Java-Bytecode
entsteht, werden Java-Programme schneller abgearbeitet, als vergleichbare
interpretierte Sprachen. Wie man im obigen Beispiel
eines Java-Bytecodes sieht, ist der Bytecode sehr maschinennah gestaltet,
wodurch der Interpreter der Java Virtual Machine die Umsetzung in Maschinencode
sehr schnell vornehmen kann.
Weiterhin bietet Java die Möglichkeit, Applikationen zu entwickeln,
die Multithreading unterstützen, wodurch eine weitere Möglichkeit
zur (subjektiven) Geschwindigkeitssteigerung besteht. Multithreading bedeutet,
daß verschiedene Teile eines Programms parallel ablaufen können.
Ein Beispiel wäre das Neuzeichnen einer Grafik mit einem Grafikprogramm,
während im selben Grafikprogramm eine andere Grafik gespeichert wird.
Der Anwender kann also mit einer Applikation weiterarbeiten, während
von der Anwendung im Hintergrund eine umfangreiche Aufgabe ausgeführt
wird.
Eine weitere Möglichkeit zur Steigerung der Ausführungsgeschwindigkeit
von Java-Programmen bietet das Linken von Modulen, die in einer anderen
Programmiersprache, beispielsweise C++, geschrieben wurden. Dies ist allerdings
nur unter dem Verlust der Portabilität möglich.
2.2.5 Leichte Erlernbarkeit
Bei der Entwicklung von Java wurde vor allem darauf geachtet, daß
ein Programmierer, der schon Erfahrungen mit anderen Programmiersprachen
hat, schnell lernen kann, Java-Programme zu schreiben. Aus diesem Grund
ist Java von der syntaktischen und lexikalischen Struktur stark an C++,
der verbreitesten objektorientierten Programmiersprache, angelehnt.
In Java wurden jedoch einige kritische Punkte von C++ weggelassen beziehungsweise
vereinfacht. So wurde in Java zum Beispiel keine Zeigerarithmetik implementiert,
da daraus viele potentielle Fehlerquellen entstünden. Als plattformunabhängige
Programmiersprache ist es mit Java dem Programmierer nicht möglich,
direkten Zugriff auf den Speicher des Rechners zu erlangen. Auch die zusammengesetzten
Datentypen von C++ (struct, union) wurden in Java weggelassen,
da die gleiche Funktionalität auch mit Klassen möglich ist. Weiterhin
wurde der Mechanismus der Mehrfachvererbung (Polymorphismus) geändert.
Eine Auflistung der wichtigsten Unterschiede zwischen Java und C++ zeigt
folgende Tabelle:
Feature |
Java |
C++ |
Zeiger |
- |
int *a,b; a=&b; |
Zeichen |
16-Bit-Unicode |
Byte |
Zeichenketten |
String-Objekte |
Arrays |
Boolesche Werte |
Boolean ist Basisdatentyp |
- |
Felder (Arrays) |
Felder sind Objekte, es findet eine Überprüfung der Grenzen
statt (bound-checking) |
statische Allozierung des Speichers, es findet kein bound-checking
statt |
Aufzählungstyp |
- |
enum {...}; |
Typdefinition |
- |
typedef {...}; |
Zusammengesetzte Datentypen |
- |
struct a {...};
union b {...}; |
Preprocessor |
- |
vorhanden |
Einbinden von Modulen |
import <interface> |
#include |
Mehrfachvererbung |
class a extends b implements c {...} |
class a: public b, public c {...} |
Templates |
- |
template <class a> |
Überladen von Operatoren |
- |
möglich |
Thread-Support |
vorhanden |
- |
Heap-Verwaltung |
Automatische Garbage Collection im Hintergrund |
Manuelle Freigabe von Blöcken durch den Programmierer |
Tabelle 2.1: Unterschiede zwischen Java und C++ (Quelle: BACK
1996)
2.2.6 Sicherheit
Bei einer Programmiersprache, deren Programme hauptsächlich durch
ein Netzwerk (dem Internet) vertrieben werden sollen, ist es besonders
wichtig, Wert auf ein umfassendes Sicherheitskonzept zu legen. Die Entwickler
von Sun wollten somit vermeiden, daß man sich mit einem Java-Programm
einen Virus oder ein trojanisches Pferd auf den Rechner lädt. Das
Sicherheitskonzept besteht aus folgenden Komponenten:
Sprachgestaltung von Java
Schon bei der Sprachgestaltung von Java wurde versucht, potentielle Risiken
so weit wie möglich auszuschalten. So ist beispielsweise durch die
fehlende Zeigerarithmetik kein Zugriff auf den Hauptspeicher des Rechners
möglich, wodurch einige Mißbrauchsmöglichkeiten ausgeschlossen
werden. Weiterhin erfolgen die Funktions- und Variablenaufrufe über
den Namen und nicht über eine Speicheradresse, so daß auch hier
Gefahrquellen weitgehend ausgeschlossen sind.
Bytecode-Prüfungen
Der Java-Compiler überprüft nur die syntaktische Korrektheit
eines Java-Programms. Außerdem kann der Bytecode theoretisch nach
der Kompilierung noch geändert werden. Vor dem Start eines Java-Applets
bzw. einer Java-Anwendung wird der Bytecode daher durch einen Bytecode-Checker
überprüft. Damit soll sichergestellt werden, daß nur korrekte
Member-Variablen und -Methoden in den Bytecode-Interpreter gelangen.
Zunächst werden die vom Compiler erstellten Prüfsummen auf
ihre Korrektheit überprüft. Weiterhin wird sichergestellt, daß
die Datentypen aller Parameter einer Funktion mit den in den Funktionsaufrufen
verwendeten übereinstimmen. Eventuell wird dabei eine Casting-Operation
durchgeführt. Es erfolgt auch eine Überprüfung, ob Variablen
oder -Methoden verwendet werden, die auf Objekte verweisen, auf die sie
keinen Zugriff besitzen.
Das Java-System ist somit in der Lage festzustellen, ob der Bytecode
eines Java-Programms im Nachhinein (absichtlich oder unabsichtlich) verändert
wurde. Dadurch verringert sich zum einen die Gefahr, daß ein Java-Programm
durch fehlerhafte Anweisungen abstürzt, zum anderen wird es dadurch
sehr schwierig, durch Veränderungen am Bytecode ein Virus zu erstellen.
Class-Loader
Der Class-Loader ist für die sogenannte Class Name Space verantwortlich.
Die Class Name Space ist der Speicherplatz für Java-Klassen. Das Java-System
unterscheidet zwischen Systemklassen und importierten Klassen. Systemklassen
stellen die Schnittstelle zum lokalen Rechnersystem dar und haben daher
alle Möglichkeiten, auf das Rechnersystem zuzugreifen. Importierte
Klassen hingegen werden als Teile eines Java-Applets aus dem Internet geladen
und haben nur eingeschränkte Zugriffsrechte. Aus diesem Grund werden
die Systemklassen und importierten Klassen getrennt voneinander gespeichert.
Beim Aufruf einer Methode oder Verweis auf eine Variable wird zunächst
die Name Space der Systemklassen, dann die Name Space der importierten
Klassen durchsucht. Dadurch wird verhindert, daß ein Applet als Systemklasse
angesehen wird.
Beschränkter Zugriff auf Systemressourcen
Je nach Herkunft des Java-Programms wird der Zugriff auf die Systemressourcen
des lokalen Rechnersystems eingeschränkt. Hierbei wird zwischen den
Applikationen, also den Stand-Alone-Programmen und den Applets, die im
Rahmen einer HTML-Seite aus dem Internet geladen werden unterschieden.
Für die Applikationen, gelten wie auch bei anderen Programmiersprachen
keinerlei Einschränkungen, wohingegen den Applets der Zugriff auf
die Systemressourcen, wie zum Beispiel die Festplatte, verwehrt bleibt.
Die Applets laufen dabei in der sogenannten Sandbox ab (vgl. Abb.
2.2)
Abb. 2.2: Zugriff von Applikationen und Applets auf die Systemressourcen
(Quelle: LUCKHARDT
1997)
Weiterhin besitzen Applets nicht das Recht, fremde Programme, wie zum
Beispiel ein Festplattenformatierungsprogramm, auf dem Rechnersystem, auf
dem sie laufen, zu starten. Auch Netzwerkverbindungen dürfen nur zu
dem Rechner aufgebaut werden, von dem das Applet geladen wurde.
Probleme des Java-Sicherheitskonzepts
Das hohe Niveau an Sicherheit, das Java bietet, schafft auch einige Probleme:
Zum einen erfordern die vielen Prüfungen einen gewissen Zeitaufwand,
so daß die Ausführungsgeschwindigkeit der Java-Programme leidet.
Zum anderen ist es schwierig, vernünftige Anwendungsgebiete für
Applets zu finden, wenn diesen der Zugriff auf das lokale Rechnersystem
völlig verwehrt bleibt. Dieses Problem wurde jedoch erkannt und zur
Lösung werden mit dem JDK 1.2 signierte Applets eingeführt.
Ein Applet kann dabei mit einer digitalen Signatur versehen werden, womit
Integrität und Herkunft eines Applets zweifelsfrei überprüft
werden können. Ein solches Applet kann dann von dem Anwender die Freigabe
bestimmter Ressourcen auf dem lokalen Rechnersystem verlangen. Da die Herkunft
und die Integrität des Applets gesichert ist, geht der Anwender mit
der Freigabe bestimmter Ressourcen nur noch ein sehr geringes Risiko ein.
2.3 Integration von Java-Applets in eine Webpage
Die Integration eines Java-Programms in eine Webpage gestaltet sich dank
des neuen HTML-Tags <APPLET> sehr einfach. Ein Applet bekommt
dabei einen bestimmten Teil der Seite zugewiesen, in dem es "residiert".
Folgendes Beispiel soll dies verdeutlichen:
<HTML>
<HEAD>
<APPLET CODE=a.class width=200 height=200>
<PARAM name=param1 value=21>
</APPLET>
...
</HTML>
In diesem Beispiel bekommt das Applet mit dem Namen "a" einen Bereich
von 200 mal 200 Punkten auf der HTML-Seite zugewiesen. Wie man sieht, ist
auch eine Parameterübergabe an das Applet möglich. Hier wird
dem Parameter mit dem Namen "param1" der Wert "21" zugewiesen. Der restliche
Teil des HTML-Codes ist genauso aufgebaut wie bei einer HTML-Seite ohne
ein Java-Applet. Eine große Zahl an Applets findet sich zum Beispiel
unter http://java.sun.com/applets/
Ein Vorteil von Java bleibt dabei, daß nur der Bytecode über
das Netz übertragen wird, den Sourcecode kann also niemand sehen.
Damit ist das geistige Eigentum des Entwicklers weitgehend geschützt.
[Zurück]
[Inhalt]
[Weiter]