<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//DE">
<!--Converted with LaTeX2HTML 96.1-h (September 30, 1996) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds -->
<HTML>
<HEAD>
<TITLE>Die Java Virtual Machine</TITLE>
<META NAME="description" CONTENT="Die Java Virtual Machine">
<META NAME="keywords" CONTENT="java">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<LINK REL=STYLESHEET HREF="java.css">
</HEAD>
<BODY LANG="DE" >
  
<P>
<H1 ALIGN=CENTER>Die Java Virtual Machine</H1>
<P ALIGN=CENTER><STRONG>Jens Schwarz<A NAME="tex2html1" HREF="#6"><IMG  ALIGN=BOTTOM ALT="gif" SRC="file:/usr/lib/latex2html/icons/foot_motif.gif"></A></STRONG></P><P>
<P ALIGN=CENTER><STRONG>T&#252;bingen, den 3. August 1998
</STRONG></P><P>
<P>
<P><H2><A NAME="SECTION00100000000000000000">Inhalt</A></H2>
<UL><A NAME="CHILD_LINKS">&#160;</A>
<LI> <A NAME="tex2html13" HREF="java.html#SECTION00200000000000000000">Java Virtual Machine</A>
<UL>
<LI> <A NAME="tex2html14" HREF="java.html#SECTION00210000000000000000">Einleitung</A>
<LI> <A NAME="tex2html15" HREF="java.html#SECTION00220000000000000000">Die Java Virtual Machine</A>
<UL>
<LI> <A NAME="tex2html16" HREF="java.html#SECTION00221000000000000000">Datentypen</A>
<LI> <A NAME="tex2html17" HREF="java.html#SECTION00222000000000000000">Bytecode</A>
<LI> <A NAME="tex2html18" HREF="java.html#SECTION00223000000000000000">Der Aufbau der Java Virtual Machine</A>
<UL>
<LI> <A NAME="tex2html19" HREF="java.html#SECTION00223100000000000000">Die Laufzeitumgebung</A>
<LI> <A NAME="tex2html20" HREF="java.html#SECTION00223200000000000000">Register</A>
<LI> <A NAME="tex2html21" HREF="java.html#SECTION00223300000000000000">Stack</A>
<LI> <A NAME="tex2html22" HREF="java.html#SECTION00223400000000000000">Heap</A>
<LI> <A NAME="tex2html23" HREF="java.html#SECTION00223500000000000000">Speicherbereich f&#252;r Methoden</A>
</UL> 
</UL> 
<LI> <A NAME="tex2html24" HREF="java.html#SECTION00230000000000000000">Die Class-Datei</A>
<UL>
<LI> <A NAME="tex2html25" HREF="java.html#SECTION00231000000000000000">Format</A>
<LI> <A NAME="tex2html26" HREF="java.html#SECTION00232000000000000000">Konstantenpool</A>
<LI> <A NAME="tex2html27" HREF="java.html#SECTION00233000000000000000">Methoden</A>
<LI> <A NAME="tex2html28" HREF="java.html#SECTION00234000000000000000">Attribute</A>
</UL> 
<LI> <A NAME="tex2html29" HREF="java.html#SECTION00240000000000000000">Besonderheiten der Java Virtual Machine</A>
<UL>
<LI> <A NAME="tex2html30" HREF="java.html#SECTION00241000000000000000">Die Freispeicherverwaltung</A>
<LI> <A NAME="tex2html31" HREF="java.html#SECTION00242000000000000000">Multithreading</A>
<LI> <A NAME="tex2html32" HREF="java.html#SECTION00243000000000000000">Ausnahmen</A>
<LI> <A NAME="tex2html33" HREF="java.html#SECTION00244000000000000000">Laufzeit</A>
</UL> 
<LI> <A NAME="tex2html34" HREF="java.html#SECTION00250000000000000000">Ausf&#252;hrungsmodelle</A>
<UL>
<LI> <A NAME="tex2html35" HREF="java.html#SECTION00250100000000000000">Java Interpreter</A>
<LI> <A NAME="tex2html36" HREF="java.html#SECTION00250200000000000000">Just-in-Time Compiler</A>
<LI> <A NAME="tex2html37" HREF="java.html#SECTION00250300000000000000">Java Prozessoren</A>
</UL> 
</UL> 
<LI> <A NAME="tex2html38" HREF="java.html#SECTION00300000000000000000">Java Prozessoren (picoJava I)</A>
<UL>
<LI> <A NAME="tex2html39" HREF="java.html#SECTION00310000000000000000">Stack Architektur</A>
<LI> <A NAME="tex2html40" HREF="java.html#SECTION00320000000000000000">Pipeline</A>
<LI> <A NAME="tex2html41" HREF="java.html#SECTION00330000000000000000">Dribbler</A>
<LI> <A NAME="tex2html42" HREF="java.html#SECTION00340000000000000000">Zusammenfassung</A>
</UL> 
<LI> <A NAME="tex2html43" HREF="java.html#SECTION00400000000000000000">Abbildungsverzeichnis</A>
<LI> <A NAME="tex2html44" HREF="java.html#SECTION00500000000000000000">Literatur</A>

</UL>
<H1><A NAME="SECTION00200000000000000000">Java Virtual Machine</A></H1>
<P>
<H1><A NAME="SECTION00210000000000000000">Einleitung</A></H1>
<P>
Die Entwicklung von Java<A NAME="tex2html2" HREF="#11"><IMG  ALIGN=BOTTOM ALT="gif" SRC="file:/usr/lib/latex2html/icons/foot_motif.gif"></A> wurde von Sun-Microsystems 1991 im Rahmen eines Forschungsprojektes zur Entwicklung von Software f&#252;r eingebettete Systeme in Konsumelektronikger&#228;ten, wie z.B. Fernseher, Videorecorder, Toaster und anderen Haushaltsger&#228;te, begonnen. Deshalb sollte die Sprache klein, schnell, sicher und leicht portierbar sein. Das gleiche Ziel macht Java zu einer idealen Sprache zur Verbreitung ausf&#252;hrbarer Programme &#252;ber das World-Wide-Web. Das gesamte Java-Konzept l&#228;&#223;t sich in drei Teile gliedern. Es besteht nach Dalheimer  [<A HREF="java.html#JVM">Da</A>] aus:
<DL ><DT><DD><EM>der Programmiersprache</EM>, die objektorientiert ist und deren Syntax C++ &#228;hnelt, gleichzeitig jedoch viele Schwierigkeiten, wie sie in C++ auftreten nicht kennt.
<DT><DD><EM>dem Maschinenmodell</EM>, auf dem Java Programme, aber auch Programme anderer Sprachen, die Werkzeuge besitzen, um Quellcode in <TT>class</TT>-Dateien (Dateien die Daten und den Maschinencode enthalten, den die Java Virtual Machine ausf&#252;hrt, siehe <A HREF="java.html#cl">1.3</A>) zu &#252;bersetzen, ablaufen.
<DT><DD><EM>der Entwicklungsumgebung</EM>, die f&#252;r die Erstellung, die &#220;bersetzung und den Ablauf von Java Programmen n&#246;tig ist. Sie enth&#228;lt einen Java-Compiler, der den Quelltext in <TT>class</TT>-Dateien &#252;bersetzt. Zur Ausf&#252;hrung dieser Dateien ist dann ein Java-Interpreter, ein Just-in-Time-Compiler oder ein Java-Prozessor n&#246;tig.
<P>
</DL>
Die besonderen Eigenschaften die Java bietet und die durch die Idee der virtuellen Maschine m&#246;glich sind, werden im ,,White Paper``&#252;ber Java von JavaSoft durch elf Schlagworte beschrieben:
<DL ><DT><DD> <EM>einfach:</EM> Die Sprache soll einfach zu programmieren sein. Um das System leicht verst&#228;ndlich zu halten, wurde Java so C++ &#228;hnlich wie m&#246;glich entworfen. Einer der gr&#246;&#223;ten Unterschiede bildet hier der Verzicht auf Zeiger, der eine erh&#246;hte Betriebssicherheit erm&#246;glicht.
<DT><DD> <EM>objektorientiert:</EM> die objektorientierten Konstrukte von Java sind denen von C++ sehr &#228;hnlich. Ein gro&#223;er Teil der objektorientierten Konstrukte wird zwar bereits vom Compiler aufgel&#246;st, das Objekt-Konzept ist jedoch auch in der Java Virtual Machine vorhanden, z.B. in Befehlen zum Anlegen von Objekten oder Spr&#252;ngen auf virtuelle Methoden.
<DT><DD> <EM>verteilt:</EM> Java erm&#246;glicht einfaches Arbeiten in Netzwerken und im Internet. Dies wird jedoch durch mitglieferte Netzwerkbibliotheken erreicht und ist somit kein Kennzeichen von Java oder der Java Virtual Machine. 
<DT><DD> <EM>robust:</EM> Mit Java erstellte Programme sollen verl&#228;&#223;lich sein. Es wird versucht Probleme und Fehler m&#246;glichst fr&#252;h zu erkennen. Durch die Ausnahme-Behandlung werden Fehler abgefangen und zur Laufzeit werden die vorliegenden <TT>class</TT>-Dateien &#252;berpr&#252;ft.
<DT><DD> <EM>sicher:</EM> F&#252;r den Einsatz in verteilten und Netzwerk-Umgebungen ist Sicherheit von gro&#223;er Bedeutung. Java hat daf&#252;r ein mehrstufiges Sicherheitssystem.
<DT><DD> <EM>architekturneutral und portabel:</EM> Java Programme sind auf jedem Rechner der eine Java Virtual Machine implementiert, abblauff&#228;hig und es gibt keine implementationsabh&#228;ngigen Erscheinungen. Die Gr&#246;&#223;e und arithmetischen Funktionen der primitiven Datentypen sind genau definiert.
<DT><DD> <EM>interpretiert:</EM> Java-Bytecode kann von einem Java-Interpreter auf jeder Maschine direkt ausgef&#252;hrt werden, es ist kein gesonderter Link-Vorgang notwendig. Heutige Java-Interpreter interpretieren den Bytecode w&#228;hrend der Ausf&#252;hrung. Dies f&#252;hrt zu Geschwindigkeitseinbu&#223;en.
<DT><DD> <EM>schnell:</EM> Im Vergleich zu C++ sind Java-Programme auf Grund des Interpreters noch langsam. Aber Just-in-time-Compiler oder Java-Prozessoren k&#246;nnten Abhilfe schaffen.
<DT><DD> <EM>Multithreading:</EM> Multithreading erlaubt es einem Programm mehrere Programmteile gleichzeitig ablaufen zu lassen. Hierf&#252;r werden Threads benutzt, f&#252;r die Techniken vorhanden sind, die Probleme wie die Synchronisation l&#246;sen. &#196;hnlich wie beim Multitasking, bei dem mehrere Programme gleichzeitig ablaufen, ist dies besonders auf einem Mehrprozessorsystem interessant. Die Freispeicherverwaltung des Java-Systems l&#228;uft in einem eigenen Thread.
<DT><DD><EM>dynamisch:</EM> Java ist eine dynamischere Sprache als C++. Klassenbibliotheken k&#246;nnen neue Methoden oder Instanzvariablen hinzuf&#252;gen ohne da&#223; die Benutzer der Bibliothek davon betroffen sind und eine Neu&#252;bersetzung des Programms, das diese Bibliothek benutzt, notwendig wird.
<P>
</DL>
Ein zentraler Bestandteil des Java-Konzepts bildet die Java Virtual Machine. Bei der Spezifikation dieser abstrakten, logischen, virtuellen Maschine sollen alle Einzelheiten einer Implementierung au&#223;er Acht gelassen werden.
<P>
<H1><A NAME="SECTION00220000000000000000">Die Java Virtual Machine</A></H1>
<P>
Bei der Entwicklung des Java-Konzepts wurde Wert darauf gelegt, f&#252;r eine Implementierung der Java Virtual Machine m&#246;glichst keine Vorgaben zu machen, um die jeweiligen M&#246;glichkeiten der zu Grunde liegenden Plattform optimal nutzen zu k&#246;nnen. Die Java Virtual Machine wird gleichzeitig genau spezifiziert (z.B. die elementaren Datentypen). Dadurch sind Java-Klassen plattformunabh&#228;ngig und portabel.
<H2><A NAME="SECTION00221000000000000000">Datentypen</A></H2>
<P>
F&#252;r die Java Virtual Machine sind sieben elementare und zwei interne Datentypen erkl&#228;rt, deren Gr&#246;&#223;en genau festgelegt sind. So sind z.B. Integer-Werte immer 4 Bytes gro&#223;. Es werden vorzeichenbehaftete Ganzzahlen im Zweierkomplement,  Flie&#223;kommazahlen einfacher oder doppelter Genauigkeit im IEEE 754-Format und Zeichenwerte unter anderem im Unicode-Format benutzt. 
<H2><A NAME="SECTION00222000000000000000">Bytecode</A></H2>
<P>
Bei herk&#246;mmlichen Programmiersprachen wird der Quelltext entweder nach der Erstellung in nativen Maschinencode f&#252;r bestimmte Prozessoren &#252;bersetzt (Compiler) oder zur Laufzeit interpretiert (Interpreter). Java Programme hingegen werden zun&#228;chst in eine Maschinensprache f&#252;r die Java Virtual Machine, den Bytecode, &#252;bersetzt. Dieser in einer <TT>class</TT>-Datei gespeicherte Code kann dann auf jeder Maschine die eine Java Virtual Machine implementiert zum Ablauf gebracht werden (Abbildung <A HREF="java.html#ab1">1.1</A> und <A HREF="java.html#ab2">1.2</A>).<BR> 
<P><A NAME="199">&#160;</A><IMG WIDTH=396 HEIGHT=294 ALIGN=BOTTOM ALT="figure40" SRC="img1.gif"><BR>
<STRONG>Abbildung:</STRONG> <A NAME="ab1">&#160;</A> Kompilierung herk&#246;mmlicher Programme  [<A HREF="java.html#T21">LP</A>]<BR>
<P>
<P><A NAME="200">&#160;</A><IMG WIDTH=567 HEIGHT=386 ALIGN=BOTTOM ALT="figure45" SRC="img2.gif"><BR>
<STRONG>Abbildung 1.2:</STRONG> <A NAME="ab2">&#160;</A> Kompilierung eines Java-Programms  [<A HREF="java.html#T21">LP</A>]<BR>
<P><BR> <BR> 
Die Maschinenbefehle werden dabei durch ein Byte lange Opcodes dargestellt. Die Anzahl und Gr&#246;&#223;e der direkt nachfolgenden Operanden ist vom jeweiligen Opcode abh&#228;ngig. Im Gegensatz zu manchen realen Prozessoren (mit einem kleinsten Opcode von 16 Bit) verlangt die Java Virtual Machine nicht, da&#223; 16 Bit gro&#223;e Operanden an durch zwei teilbaren Adressen liegen. Auf solchen Rechnerarchitekturen kann dies von Nachteil sein, da aber normalerweise keine F&#252;llbytes notwendig werden, f&#252;hrt dies zu kompakterem Code. Dies ist vor allem deshalb wichtig, da die Netzgeschwindigkeit, z.B. im Internet, fast immer mehr Zeitanteil als die tats&#228;chliche Ausf&#252;hrung des Programms in Anspruch nimmt.<BR> <BR> 
Die L&#228;nge von einem Byte erm&#246;glicht 256 Befehle, von denen momentan ungef&#228;hr 200 definiert sind. Sie lassen sich wie folgt unterteilen:
<EM> <DL COMPACT><DT>
<DD>Laden von Konstanten auf den Stack
<DT>
<DD>Laden und Speichern von lokalen Variablen
<DT>
<DD> Stackmanipulation
<DT>
<DD>Arithmetische Anweisungen
<DT>
<DD>Logische Anweisungen
<DT>
<DD>Indexerweiterung
<DT>
<DD>Opcodes zur Array-Behandlung
<DT>
<DD>Umwandlungsoperationen
<DT>
<DD>Vergleichs- und Sprungbefehle
<DT>
<DD>Aufruf von Methoden und R&#252;cksprung aus Methoden
<DT>
<DD>Sprungtabellen
<DT>
<DD>Zugriff auf Objektfelder
<DT>
<DD>Opcodes zur Unterst&#252;tzung von Ausnahmebehandlung
<DT>
<DD>Opcodes zur Unterst&#252;tzung von Parallelverarbeitung
<DT>
<DD>Diverse weitere Operationen
<P>
</DL></EM>
Jeder Opcode besitzt eine bestimmte Anzahl von Operanden, die direkt nach ihm im Bytecode gespeichert sind. Die Operanden der Befehle <TT>tableswitch</TT> und <TT>lookupswitch</TT> m&#252;ssen an einer durch vier teilbaren Position im Bytecode liegen. Dies sind die einzigen F&#228;lle in denen F&#252;llbytes notwendig sind.<BR> <BR> 
Da die Java Virtual Machine keine Register zur Speicherung von Operanden und Ergebnissen von Befehlen benutzt, liegen diese auf einem Operandenstack. Z.B. erwartet der f&#252;r die Addition zust&#228;ndige Opcode <TT>iadd</TT> (Abbildung <A HREF="java.html#Byte">1.3</A>) zwei Integer-Werte (16-Bit), die er vom Operandenstack nimmt, addiert und deren Summe wieder auf dem Operandenstack ablegt. Der Opcode <TT>new</TT> (Abbildung <A HREF="java.html#Byte">1.3</A>) erwartet zwei Bytes als Operanden, die zu einem Index in den Konstantenpool zusammengesetzt werden. Dort steht ein Klasseneintrag, aus dem die Klasse bestimmt wird, von der ein neues Objekt instanziert und eine Objektreferenz darauf auf den Operandenstapel gelegt wird. In der folgenden Grafik sind zun&#228;chst die Formate dieser Befehle im Bytecode, anschlie&#223;end jeweils das obere Ende des Stacks vor (links) und nach (rechts) der Operation dargestellt.<BR> 
<P><A NAME="201">&#160;</A><IMG WIDTH=574 HEIGHT=189 ALIGN=BOTTOM ALT="figure75" SRC="img3.gif"><BR>
<STRONG>Abbildung 1.3:</STRONG> <A NAME="Byte">&#160;</A> Die Befehle iadd und new<BR>
<P><BR> 
Der Bytecode einer <TT>class</TT>-Datei wird einem Java-Interpreter &#252;bergeben, der nach der Initialisierung und dem Laden etwa folgende Schleife ausf&#252;hrt:
<A NAME="intp">&#160;</A>
<TT> <PRE><TT> 
do
<P>
{
<P>
		get_next_opcode();
<P>
		get_operands();
<P>
		execute_opcode();
<P>
		if( !opcode_advanced_pc_register )
<P>
				advance_pc_register();
<P>
} while (opcodes_left());
<P>
</TT></PRE></TT><H2><A NAME="SECTION00223000000000000000">Der Aufbau der Java Virtual Machine</A></H2>
<P>
Die Java Virtual Machine verf&#252;gt &#252;ber einen Heap, einen Stack, einen Methodenbereich und verschiedene Register zur internen Verwaltung. In Abbildung <A HREF="java.html#struktur">1.4</A> ist der Zusammenhang der einzelnen Bestandteile dargestellt.<BR> 
<P><A NAME="202">&#160;</A><IMG WIDTH=572 HEIGHT=570 ALIGN=BOTTOM ALT="figure87" SRC="img4.gif"><BR>
<STRONG>Abbildung 1.4:</STRONG> <A NAME="struktur">&#160;</A>Die Java Virtual Machine<BR>
<P><BR> 
Der Java-Stapel und der Operandenstapel sind nicht identisch. Jeder Thread der Java Virtual Machine verf&#252;gt &#252;ber einen eigenen Java-Stapel, jeder Rahmen (engl. frame) einer Methode &#252;ber einen eigenen Operandenstapel  [<A HREF="java.html#TM">LY</A>].<BR> 
Der Konstantenpool einer Klasse ist auch im Methodenbereich gespeichert. Die Befehle der Java Virtual Machine arbeiten auf dem Operandenstapel, da keine Datenregister vorhanden sind.
<H3><A NAME="SECTION00223100000000000000">Die Laufzeitumgebung</A></H3>
<P>
Die auf dem Java-Stapel abgelegten Rahmen speichern die Laufzeitumgebung der einzelnen Methoden. Sie enthalten Informationen, die die Java Virtual Machine w&#228;hrend der Laufzeit eines Programms ben&#246;tigt. Die normalen Funktionen der Rahmen sind: dynamisches Binden, Parameter&#252;bergabe, R&#252;ckspr&#252;nge aus Methoden und das Weiterreichen von Ausnahmezust&#228;nden und Fehlern. Die Rahmen enthalten weiter die lokalen Variablen, einen Operandenstapel, die Register der aufrufenden Methode. Je nach reaImplementierung k&#246;nnen sie auch Debugging-Informationen und &#196;hnliches enthalten.
<H3><A NAME="SECTION00223200000000000000">Register</A></H3>
<P>
Die Anzahl und Gr&#246;&#223;e der Register eines Prozessors beeinflussen seine Leistungsf&#228;higkeit, da er auf diese ,,internen``  Speichereinheiten besonders schnell zugreifen kann. Obwohl die Java Virtual Machine eine Spezifikation f&#252;r einen Prozessor ist, besitzt sie keine Register in die Daten zur Ausf&#252;hrung von Operationen geladen werden. Dadurch k&#246;nnen Java Programme auch auf Prozessoren mit wenig Registern relativ effizient ablaufen. Die Java Virtual Machine f&#252;hrt ihre Operationen auf dem Operandenstapel aus. Zur internen Verwaltung besitzt sie dennoch vier Register: pc, vars, optop und frame (diese Bezeichnungen m&#252;ssen nicht verwendet werden, haben sich aber eingeb&#252;rgert).
<DL ><DT><DD> Das <B>pc</B>-Register (program counter) enth&#228;lt die Adresse des n&#228;chsten auszuf&#252;hrenden Opcodes. Die Java Virtual Machine liest das an der durch pc gegebenen Adresse liegende Byte ein, interpretiert es als Opcode und liest je nach Opcode verschieden viele Operanden ein. Danach wird pc auf das als n&#228;chstes zu lesende Byte gesetzt.
<DT><DD> Das <B>optop</B>-Register zeigt auf den obersten Wert im Operanden-Stack, der zur Auswertung aller arithmetischen Ausdr&#252;cke dient. 
<DT><DD> Das <B>frame</B>-Register zeigt auf den Rahmen der aktuellen Methode.
<DT><DD> Das <B>vars</B>-Register zeigt auf die lokalen Variablen der aktuellen Methode.
<P>
</DL> 
Die lokalen Variablen einer Java-Methode werden in aufeinanderfolgenden 32 Bit breiten Speicherpl&#228;tzen abgelegt, die von 0 an fortlaufend numeriert sind. 64 Bit breite Datentypen belegen zwei Positionen. Die Aufteilung f&#252;r 64-Bit Werte ist beliebig  und ungerade Positionen sind m&#246;glich. Jeder Thread besitzt diese vier Register.
<H3><A NAME="SECTION00223300000000000000">Stack</A></H3>
<P>
Der Java-Stapel ist das wichtigste Element der Java Virtual Machine, da sie keine Datenregister besitzt. Er speichert die Rahmen der einzelnen Methoden, die die Operanden-Stapel enthalten, auf denen gerechnet wird. Der Java-Stapel entspricht nicht dem Stack der realen Maschine, auf der ein Java Programm abl&#228;uft, sondern einer eigenen Datenstruktur, die von der Java Virtual Machine verwaltet wird, die je nach Implementierung eine feste Gr&#246;&#223;e besitzen, expandieren oder auch schrumpfen kann. Der Java-Stapel besteht aus 32-Bit breiten Eintr&#228;gen. 64-Bit Datentypen, wie z.B. long-Werte, benutzen zwei Positionen.<BR> 
Die Bytecode-Befehle arbeiten auf dem Operandenstapel, den jeder Rahmen enth&#228;lt.
<H3><A NAME="SECTION00223400000000000000">Heap</A></H3>
<P>
Auf dem Heap der Java Virtual Machine werden neu erstellte Instanzen (Objekte) abgelegt. Ob die Java Virtual Machine f&#252;r jedes Objekt vom Betriebsystem des Rechners Speicher anfordert oder einen gr&#246;&#223;eren Speicherbereich selbst als Heap verwaltet, ist nicht spezifiziert. Da die Java Virtual Machine mit einer Freispeicherverwaltung arbeitet, mu&#223; der Programmierer den nicht mehr ben&#246;tigten Speicher nicht wieder freigeben (und kann dies auch nicht). Mit welcher Technik eine Java Virtual Machine die Freispeicherverwaltung durchf&#252;hrt ist nicht festgelegt. Ebensowenig der Zeitpunkt. Jedoch kann mit einem Aufruf der Methode gc() (Garbage Collection) eine Speicherbereinigung erzwungen werden.
<H3><A NAME="SECTION00223500000000000000">Speicherbereich f&#252;r Methoden</A></H3>
<P>
Im Methodenbereich werden die Strukturen der Klassen, also der Konstantenpool, die Methodendaten und der Bytecode der Methoden und Konstruktoren gespeichert. Er wird beim Starten der Java Virtual Machine angelegt und von allen Threads gemeinsam genutzt. Weder der Speicherort des Methodenbereichs noch die Verwaltung des Bytecode ist festgelegt. Der Methodenbereich kann eine feste Gr&#246;&#223;e haben, expandieren oder schrumpfen und mu&#223; nicht zusammenh&#228;ngend sein.
<H1><A NAME="SECTION00230000000000000000">Die Class-Datei</A></H1>
<P>
<A NAME="cl">&#160;</A>
Die <TT>class</TT>-Datei ist eine grundlegende Darstellung des Java-Systems. F&#252;r jede Klasse erzeugt der Compiler eine <TT>class</TT>-Datei. In ihr werden verschiedene Informationen &#252;ber die Klasse und der Bytecode gespeichert.
<H2><A NAME="SECTION00231000000000000000">Format</A></H2>
<P>
Die <TT>class</TT>-Datei besitzt ein genau definiertes Format, das nachfolgend dargestellt ist:
<TT> <PRE><TT> 
		Klassendatei
<P>
		{
<P>
				int		Erkennungszahl;
<P>
				short		Subversionsnummer;
<P>
				short		Versionsnummer;
<P>
				short		Anzahl_Konstanten;
<P>
				Konstantenpooleintrag		Konstantenpool [Anzahl_Konstanten - 1];
<P>
				short		Merkmale;
<P>
				short		Klasse;
<P>
				short		Superklasse;
<P>
				short		Anzahl_Interfaces;
<P>
				short		Interfaces[Anzahl_Interfaces];
<P>
				short		Anzahl_Felder;
<P>
				Feldeintrag		Felder[Anzahl_Felder];
<P>
				short		Anzahl_Methoden;
<P>
				Methodeneintrag		Methoden[Anzahl_Methoden];
<P>
				short		Anzahl_Attribute;
<P>
				Attributeintrag		Attribute[Anzahl_Attribute];
<P>
		}
<P>
</TT></PRE></TT>
Die einzelnen Bestandteile k&#246;nnen unterschiedliche L&#228;nge besitzen, weswegen erst die gesamte class-Datei eingelesen werden mu&#223;, bevor auf alle Informationen zugegriffen werden kann. Im folgenden werden nun die wichtigen Elemente der class-Datei beschrieben.
<H2><A NAME="SECTION00232000000000000000">Konstantenpool</A></H2>
<P>
Im Konstantenpool sind s&#228;mtliche in einer Java-Klasse vorkommenden Konstanten abgelegt. Es gibt zw&#246;lf verschiedene Typen unterschiedlicher L&#228;nge, wie z.B. f&#252;r Unicode (16-Bit Zeichencodierung), Integer, Float, Class oder Methodref. Deshalb kann auf weiter hinten liegende Eintr&#228;ge erst nach &#220;berpr&#252;fung der weiter vorn liegenden zur&#252;ckgegriffen werden. Die L&#228;nge der einzelnen Eintr&#228;ge ergibt sich aus ihrem Typ oder ist mit ihnen gespeichert. Jede Klasse kann bis zu 65535 Eintr&#228;ge aufnehmen, die jeweils mit einem ein Byte gro&#223;en Feld beginnen, das den Typ des Eintrags angibt. Ein Unicode-Eintrag hat beispielsweise folgende Pseudo-C-Struktur:
<TT> <PRE><TT> 
CONSTANT_Unicode_Eintrag
<P>
{
<P>
		byte Typ;
<P>
		short L&#228;nge;
<P>
		short Zeichen[L&#228;nge];
<P>
}
<P>
</TT></PRE></TT><H2><A NAME="SECTION00233000000000000000">Methoden</A></H2>
<P>
Ein Methodeneintrag hat folgende Pseudo-C-Struktur:
<TT> <PRE><TT> 
Methodeneintrag
<P>
{
<P>
		short Merkmale;
<P>
		short Namensindex;
<P>
		short Signaturindex;
<P>
		short Anzahl_Attribute;
<P>
		Attributeintrag Attribute[Anzahl_Attribute];
<P>
}
<P>
</TT></PRE></TT>
Das Feld Merkmale speichert Merkmale der Methoden, wie public, protected, synchronized usw. Der Namensindex verweist auf eine Utf8-Konstante im Konstantenpool, die den Namen der Methode enth&#228;lt. Der Signaturindex zeigt auf eine Utf8-Konstante (Codierungsform f&#252;r Unicode mit unterschiedlicher Anzahl von Bytes je nach Zeichen) im Konstantenpool, die Typen der Parameter und des R&#252;ckgabewertes der Methode speichert. Die Attribute der Methodeneintr&#228;ge sind besonders wichtig, da der Code einer Methode im Code-Attribut und die Ausnahmentabelle im Exceptions-Attribut gespeichert sind.
<H2><A NAME="SECTION00234000000000000000">Attribute</A></H2>
<P>
Attribute beschreiben Klassen, Methoden und Felder n&#228;her. Jedes Attribut ist durch seinen Namen, eine Utf8-Konstante, gekennzeichnet. Attribute mit unbekannten Namen m&#252;ssen beim Lesen &#252;bersprungen werden. Dadurch k&#246;nnen neue Attribute (z.B. zum Debuggen) hinzugef&#252;gt werden, ohne da&#223; &#228;ltere Java-Interpreter die class-Datei nicht mehr ausf&#252;hren k&#246;nnen.<BR> 
F&#252;r Klassen existiert momentan nur das Source-File-Attribut, f&#252;r Felder nur das ConstantValue-Attribut. Methoden kennen zwei wichtige Attribute, das Code-Attribut und das Exceptions-Attribut.
<H1><A NAME="SECTION00240000000000000000">Besonderheiten der Java Virtual Machine</A></H1>
<P>
Das Java-System wird durch verschiedene Elemente der Java Virtual Machine zu einem sicheren und leistungsf&#228;higen Programmentwicklungskonzept. Besonders die Freispeicherverwaltung und Teile der Ausnahmebehandlung geh&#246;ren zu den Unterschieden zu Sprachen wie z.B. C++. Die Mechanismen f&#252;r das dem Multitasking &#228;hnliche Multithreading sind eine weitere besondere Eigenschaft der Java Virtual Machine.
<H2><A NAME="SECTION00241000000000000000">Die Freispeicherverwaltung</A></H2>
<P>
In Java wird die Freigabe nicht mehr ben&#246;tigter Objekte von der Freispeicherverwaltung der Java Virtual Machine &#252;bernommen. Fehler wie Speicherlecks, doppelte Freigabe ein und desselben Objektes oder Freigabe nie allozierten Speichers k&#246;nnen so nicht entstehen. Die einfachere Programmierung und geringere Fehleranf&#228;lligkeit wird jedoch mit gr&#246;&#223;erer Laufzeit bezahlt. Die Spezifikation der Java Virtual Machine l&#228;&#223;t die Art und Weise, wie die Garbage Collection zu geschehen hat, offen. Auch der Zeitpunkt ist nicht festgelegt. So kann je nach System ein effizientes Verfahren angewandt werden.<BR> 
Es gibt verschiedene Techniken zur Freispeicherverwaltung. Die zwei bekanntesten sind das reference-counting- und das mark-and-sweep-Verfahren. Beim reference-counting-Verfahren werden f&#252;r jedes Objekt die dazugeh&#246;rigen Referenzen gez&#228;hlt. Verschwindet eine Referenz wieder aus dem G&#252;ltigkeitsbereich, wird der Z&#228;hler erniedrigt und sobald er wieder 0 erreicht, kann das Objekt gefahrlos gel&#246;scht werden.<BR> 
Der Java-Interpreter von JavaSoft verwendet das meist geeignetere Mark-and-sweep-Verfahren. Dieses Verfahren geht von einigen immer zug&#228;nglichen Objektreferenzen (z.B. globale statische Variablen) aus. Alle dort referenzierten Objekte werden markiert und anschlie&#223;end rekursiv alle von den neu markierten Objekten referenzierte Objekte. In der folgenden Sweep-Phase werden alle nicht-markierten Objekte gel&#246;scht und die verbleibenden im Speicher verschoben, um einen zusammenh&#228;ngenden Speicherblock zu belegen. Die Freispeicherverwaltung l&#228;uft in einem eigenen Thread und somit im Hintergrund.
<H2><A NAME="SECTION00242000000000000000">Multithreading</A></H2>
<P>
Multithreading ist das Ausf&#252;hren mehrerer Teile eines Programms quasi gleichzeitig. Die einzelnen Teile werden als Threads bezeichnet. Zu den auftretenden Problemen, wie Synchronisation und die Benutzung gleicher Variablen durch verschiedene Threads, sind im Java-System L&#246;sungen, wie z.B. Monitore als Sperrmechanismen, vorhanden. Dennoch k&#246;nnen von der Zeit abh&#228;ngige Ergebnisse auftreten. Das folgende Beispiel zeigt die Problematik:<BR> <BR> 
<TT> Class Sample {
<PRE><TT> 
		int a=1,b=2;
<P>
		void hither() {
<P>
				a=b;
<P>
		}
<P>
		void yon() {
<P>
				b=a;
<P>
		}
<P>
}
<P>
</TT></PRE></TT>
Laufen die Methoden hither() und yon() der Klasse Sample jeweils in einem eigenen Thread, sind die Werte von a und b nach Ende dieser Threads nicht vorhersehbar.<BR> 
<P><A NAME="134">&#160;</A><IMG WIDTH=451 HEIGHT=339 ALIGN=BOTTOM ALT="figure131" SRC="img5.gif"><BR>
<STRONG>Abbildung 1.5:</STRONG> Multithreading<BR>
<P><BR> 
Ein Thread besitzt entweder die D&#228;moneneigenschaft oder nicht, was unter anderem f&#252;r das Ausf&#252;hrungsende eines Java-Programms von Bedeutung ist.
<H2><A NAME="SECTION00243000000000000000">Ausnahmen</A></H2>
<P>
Die Ausnahmebehandlung im Java-System ist der von C++ nachgebildet, hat aber noch einige Verbesserungen erfahren. Es werden try-Bl&#246;cke markiert, denen catch-Klauseln folgen, in denen m&#246;gliche Ausnahmen und deren Behandlung aufgef&#252;hrt sind. Es kann an jeder Stelle im Programm eine Ausnahme auftreten, f&#252;r die es m&#246;glicherweise in der catch-Klausel des aktuellen try- Block eine Behandlungsroutine gibt, die auf diese Ausnahme reagiert. Tritt eine nicht aufgef&#252;hrte Ausnahme in einem try-Block auf, wird die Ausnahme an den n&#228;chsth&#246;cheren Block weitergegeben. Wird der &#228;u&#223;erste Block erreicht, ohne da&#223; die Ausnahme behandelt wurde, bricht die Programmausf&#252;hrung ab. Zus&#228;tzlich bietet Java einen sogenannten finally-Block an, der nach verlassen des try-Blocks auf jeden Fall, ob Ausnahme oder nicht, ausgef&#252;hrt wird. Die finally-Bl&#246;cke sind f&#252;r Aufr&#228;umarbeiten gedacht und runden das Konzept der Ausnahmebehandlung ab.
<H2><A NAME="SECTION00244000000000000000">Laufzeit</A></H2>
<P>
Eine Java Virtual Machine beginnt die Ausf&#252;hrung mit dem Aufruf der main()-Methode einer angegebenen Klasse, die dadurch geladen, an andere von ihr benutzte Typen gebunden und initialisiert wird  [<A HREF="java.html#TM">LY</A>]. Liegt der Java Virtual Machine noch keine Bin&#228;rdarstellung der Klasse vor, wird der Klassenlader aufgerufen. Beim darauffolgenden Binden durchl&#228;uft der vorliegende Bytecode zun&#228;chst eine Verifikation, bei der er auf richtige Struktur und m&#246;gliche Operandenstapel&#252;ber- und unterl&#228;ufe gepr&#252;ft wird. Die Vorbereitung legt die n&#246;tigen Speicherbereiche f&#252;r die Klasse an und die optionale Aufl&#246;sung pr&#252;ft die symbolischen Referenzen zu anderen Klassen und Schnittstellen. Nach erfolgreichem Laden und Binden werden die Initialisierer in textueller Reihenfolge aufgerufen und schlie&#223;lich die main()-Methode der angegebenen Klasse ausgef&#252;hrt. Beim Abschlu&#223; einer Klasseninstanz wird die eventuell vorhandene finalize-Methode ausgef&#252;hrt.<BR> 
F&#252;r das Programmende gibt es zwei M&#246;glichkeiten. Entweder alle Threads ohne D&#228;moneneigenschaft haben ihr Ende erreicht oder ein exit-Aufruf besteht die n&#246;tige Sicherheitspr&#252;fung.
<H1><A NAME="SECTION00250000000000000000">Ausf&#252;hrungsmodelle</A></H1>
<P>
Ein Java Programm, das von einem Java-Compiler, wie z.B. javac von Java-Soft, in eine class-Datei &#252;bersetzt worden ist, kann auf jedem Rechner, der eine Java Virtual Machine implementiert, ausgef&#252;hrt werden. Dies kann durch einen Java Interpreter, einen Just-in-Time Compiler oder einen Java Prozessor geschehen (Abbildung <A HREF="java.html#exec">1.6</A>).<BR> 
<P><A NAME="204">&#160;</A><IMG WIDTH=458 HEIGHT=275 ALIGN=BOTTOM ALT="figure141" SRC="img6.gif"><BR>
<STRONG>Abbildung:</STRONG> <A NAME="exec">&#160;</A>Die drei Ausf&#252;hrungsmodelle der JVM<BR>
<P><BR> 
<H3><A NAME="SECTION00250100000000000000">Java Interpreter</A></H3>
<P>
Ein Java Interpreter interpretiert die Befehle des Bytecodes und f&#252;hrt sie aus. Daf&#252;r durchl&#228;uft er in etwa die <A HREF="java.html#intp">1.2.2</A> beschriebene Schleife. Bei jeder Ausf&#252;hrung eines Bytecode-Befehls wird dieser aufs Neue in nativen Maschinenbefehle &#252;bersetzt, die dann ausgef&#252;hrt werden.
<H3><A NAME="SECTION00250200000000000000">Just-in-Time Compiler</A></H3>
<P>
Ein Just-in-Time Compiler ist der Bestandteil mancher Java Interpreter, der w&#228;hrend der Laufzeit des Java-Programms Teile des Bytecodes in nativen Code &#252;bersetzt. Dadurch wird ein erheblicher Geschwindigkeitsgewinn erzielt, bei jedoch gleichzeitiger Expansion des Codes.
<H3><A NAME="SECTION00250300000000000000">Java Prozessoren</A></H3>
<P>
Java Prozessoren sind ,,echte``  Prozessoren, die der Spezifikation der Java Virtual Machine entsprechen und somit class-Dateien direkt ausf&#252;hren k&#246;nnen.
<H1><A NAME="SECTION00300000000000000000">Java Prozessoren (picoJava I)</A></H1>
<P>
<H1><A NAME="SECTION00310000000000000000">Stack Architektur</A></H1>
<P>
Java Prozessoren k&#246;nnten vor allem bei gro&#223;en Java Applikationen Geschwindigkeitsvorteile bringen. Auch in billigen Netzwerkcomputern und eingebetteten Systemen k&#246;nnten sie zum Einsatz kommen. <BR> Java Prozessoren, wie picoJava I von Sun Microelectronics, befinden sich noch im Planungsstadium. Aus diesem Grund werden hier nur kurz wesentliche Bestandteile dieses Prozessortyps aufgef&#252;hrt.<BR> 
Um einen Prozessor zu entwerfen, der die Java Virtual Machine effektiv implementiert, benutzt Sun Microelectronics eine einfache RISC-&#228;hnliche Architektur  [<A HREF="java.html#Sun">WP</A>].<BR> 
<P><A NAME="156">&#160;</A><IMG WIDTH=399 HEIGHT=471 ALIGN=BOTTOM ALT="figure153" SRC="img7.gif"><BR>
<STRONG>Abbildung 2.1:</STRONG> Der Aufbau von picoJava I<BR>
<P><BR> 
Der in der Mitte dargestellte Stack-Cache besitzt 64 32-Bit Register und speichert die Spitze des Java-Stack. Auf dem Java-Stack werden Parameter und lokale Variablen, Methodenrahmen und Operanden abgelegt. Bei picoJava I ist ein &#220;berlappen zwischen verschiedenen Methoden m&#246;glich, wodurch die Parameter&#252;bergabe ohne Kopiervorgang geschehen kann. <BR> 
Es k&#246;nnen mehrere, unterschiedlich gro&#223;e Rahmen im Stack-Cache liegen, aber er kann auch von einem Rahmen ausgef&#252;llt werden.<BR> 
<P><A NAME="160">&#160;</A><IMG WIDTH=576 HEIGHT=301 ALIGN=BOTTOM ALT="figure158" SRC="img8.gif"><BR>
<STRONG>Abbildung 2.2:</STRONG> Der Stack des picoJava I<BR>
<P><BR> 
Der Stack-Cache wird wie ein kreisf&#246;rmiger Puffer gemanagt. Der sogenannte ,,Dribbler``  lagert Daten beim Vollaufen des Stack-Cache in den Daten-Cache aus. Der Stack-Cache erh&#246;ht die Zugriffszeit auf die Spitze des Stacks.<BR>
<P>
<H1><A NAME="SECTION00320000000000000000">Pipeline</A></H1>
<P>
Durch Pipelining wird ein Befehl in mehrere Teile gegliedert, die alle gleichviel Zeit ben&#246;tigen. F&#252;r picoJava I wird eine einfache RISC-&#228;hnliche Pipeline mit nur vier Stufen (fetch, decode, execute, write-back) benutzt.<BR> 
Befehle zum Berechnen von Daten (z.B. iadd) arbeiten nur mit Stack-Daten und nie mit Daten aus dem Speicher. Dies erleichtert das Pipelining von Rechen- und Speicherbefehlen.<BR>
<P>
<P><A NAME="165">&#160;</A><IMG WIDTH=578 HEIGHT=259 ALIGN=BOTTOM ALT="figure163" SRC="img9.gif"><BR>
<STRONG>Abbildung 2.3:</STRONG> Die Pipeline des picoJava I<BR>
<P><H1><A NAME="SECTION00330000000000000000">Dribbler</A></H1>
<P>
Sun's Dribbler ist eine clevere Methode, um Daten zwischenzuspeichern und sie auf den Stack zur&#252;ckzugeben, wenn die Register vollaufen  [<A HREF="java.html#Byte">Wa</A>]. Sind alle 64 Register des Stack-Cache voll und es wird noch mehr Platz ben&#246;tigt, kommt diese Methode zum Einsatz. Sie l&#228;uft im Hintergrund und speichert einen Teil des Stack-Cache im Daten-Cache zwischen, um ihn auf den Stack-Cache zur&#252;ckzulegen, sobald er ben&#246;tigt wird.<BR> 
<P><A NAME="173">&#160;</A><IMG WIDTH=574 HEIGHT=464 ALIGN=BOTTOM ALT="figure169" SRC="img10.gif"><BR>
<STRONG>Abbildung 2.4:</STRONG> Der Dribbler des picoJava I<BR>
<P><H1><A NAME="SECTION00340000000000000000">Zusammenfassung</A></H1>
<P>
Momentan befinden sich Java-Prozessoren noch in der Entwicklungsphase und sind noch nicht auf dem Markt. Ob sie einen &#228;hnlichen Erfolg schaffen k&#246;nnen, wie Java selbst ist fraglich. Zwar k&#246;nnten laut Sun auf Java-Prozessoren Bytecode bis zu 12-mal schneller als auf einem Java-Interpreter ablaufen, jedoch m&#252;ssen sie mit der Entwicklung von immer schneller werdenden Just-in-time-Compilern in Verbindung mit neuen herk&#246;mmlichen Prozessoren standhalten. Der Meinung einiger Prozessoranbieter zu Folge sind ihre RISC und CISC Architekturen f&#252;r Java gut geeignet. Au&#223;erdem ist eine Umsetzung der Stapel-basierten Architektur in Hardware schwierig.
<P><H2><A NAME="SECTION00400000000000000000">Abbildungsverzeichnis</A></H2>
<UL><LI><A NAME="tex2html3" HREF="java.html#199"> Kompilierung herk&#246;mmlicher Programme  [<A HREF="java.html#T21">LP</A>]</A>
<LI><A NAME="tex2html4" HREF="java.html#200"> Kompilierung eines Java-Programms  [<A HREF="java.html#T21">LP</A>]</A>
<LI><A NAME="tex2html5" HREF="java.html#201"> Die Befehle iadd und new</A>
<LI><A NAME="tex2html6" HREF="java.html#202">Die Java Virtual Machine</A>
<LI><A NAME="tex2html7" HREF="java.html#134">Multithreading</A>
<LI><A NAME="tex2html8" HREF="java.html#204">Die drei Ausf&#252;hrungsmodelle der JVM</A>
<LI><A NAME="tex2html9" HREF="java.html#156">Der Aufbau von picoJava I</A>
<LI><A NAME="tex2html10" HREF="java.html#160">Der Stack des picoJava I</A>
<LI><A NAME="tex2html11" HREF="java.html#165">Die Pipeline des picoJava I</A>
<LI><A NAME="tex2html12" HREF="java.html#173">Der Dribbler des picoJava I</A>
</UL> <P><A NAME="SECTIONREF"><H2>Literatur</H2></A><P>
<DL COMPACT>
<DT><A NAME="JVM"><STRONG>Da</STRONG></A><DD> Matthias Kalle Dalheimer. <EM>Java Virtual Machine.</EM> O'Reilly &amp; Associates, 1997.
<DT><A NAME="Nut"><STRONG>Fl</STRONG></A><DD> David Flanagan. <EM>Java in a Nutshell.</EM> O'Reilly &amp; Associates, 1997.
<DT><A NAME="ACM"><STRONG>Go</STRONG></A><DD> James Gosling, <EM>Java Intermediate Bytecodes</EM>, ACM SIGPLAN Workshop on intermediate Representations, 1995.
<DT><A NAME="T21"><STRONG>LP</STRONG></A><DD> Laura Lemay und Charles L. Perkins. <EM>Java in 21 Tagen.</EM> SAMS, 1996.
<DT><A NAME="TM"><STRONG>LY</STRONG></A><DD> Tim Lindholm &amp; Frank Yellin. <EM>Java1exTM, Die Spezifikation der virtuellen Maschine.</EM> Addison-Wesley, 1997.
<DT><A NAME="Byte"><STRONG>Wa</STRONG></A><DD> Peter Wayner. <EM>Sun Gambles on Java Chips</EM>, Byte, November 1996.
<DT><A NAME="Tut"><STRONG>RH</STRONG></A><DD> Elliotte Rusty Harold, <EM>Brewing Java: A Tutorial</EM>, 1997.
<DT><A NAME="Sun"><STRONG>WP</STRONG></A><DD> picojava1exTM I Microprocessor Core Architecture, Sun-Microelectronics Whitepaper-0014-01, 1996
</DL>

<H1><A NAME="SECTION00600000000000000000">  Fussnoten </A></H1>
<P>

<A NAME="6">...Schwarz</A><DD>K&#228;senbachstr. 47, 72076 T&#252;bingen, Tel. 52803
<PRE>
</PRE><DT><A NAME="11">...Java</A><DD>die urspr&#252;ngliche interne Bezeichnung war Oak
<PRE>
</PRE> </DL>
<BR> <HR>
<P><ADDRESS>
<I>Gerald Heim <BR>
Mon Aug  3 22:27:46 MEST 1998</I>
</ADDRESS>
</BODY>
</HTML>
