Java Prozessoren Referat - WS 2004 Labor Computertechnik Bernd Reiners Mt.Nr.: 496 21 62 21

Die Seite wird erstellt Lui-Horst Beer
 
WEITER LESEN
Java Prozessoren Referat - WS 2004 Labor Computertechnik Bernd Reiners Mt.Nr.: 496 21 62 21
Java Prozessoren
                           Referat

Labor Computertechnik

WS 2004

Bernd Reiners

Mt.Nr.: 496 21 62 21
Java Prozessoren Referat - WS 2004 Labor Computertechnik Bernd Reiners Mt.Nr.: 496 21 62 21
Inhalt

 Einführung                                                     2
   Realisierungsmöglichkeiten                                   2
   Einsatzgebiete                                               3
   Vergleich: Java Virtual Machine – Java Prozessor             3
   Übersicht: Java Prozessoren Context                          4

 Pico Java                                                      4
   Überblick                                                    5
   Speicher der Laufzeit Umgebung                               6
   Mikroarchitektur                                             6
   Pipeline                                                     8
   der Befehlssatz                                              9
    Befehlsfomat                                                9
    Funktionale Gruppierung                                    11
    erweiterte Bytecodes                                       12
    Komplexität Handhaben - Gruppierung nach Komplexität       14
   Stackorganisation                                           16
   Instruction Folding                                         19
   Hardwareunterstützung der Laufzeitanforderungen             21
    Garbage Collection                                         22
      Mark & Sweep (markieren und rausschmeissen)              22
          Handles                                              23
      Generational Garbage Collection                          25
      Write Barriers                                           27

 Benchmark                                                     27

 Zusammenfassung                                               28

Quellen                                                        30

                                                 Seite 1/ 31
Einführung

Es gibt zwei Möglichkeiten Java direkt auszuführen: Die spezielle Softwareimplementierung
einer virtuellen Javamaschine (JVM) für Mikrocontroller oder eine Implementierung des Java-
Standards direkt in Hardware. Hier soll die zweite Möglichkeit näher betrachtet werden.

Java Prozessoren sind auf die direkte Verarbeitung von Java Bytecode optimierte CPU's.

Sie können den Bytecode direkt auf der Hardware ausführen, es kann auf das langwierige
Umsetzen des Bytecodes in native, dem Prozessor angepasste Befehle verzichtet werden
wodurch die langen Ausführungszeiten von softwarebasierten VMs entfallen

Java Prozessoren könnten als in Selikon gegossene Java Virtual Machines bezeichet
werden.

Realisierungsmöglichkeiten
Die direkte Ausführung von Bytecode in Hardware kann auf verschiedene Weise realisiert
werden.

der Java Beschleuniger
nutzt einen 'Koprozessor', der zusätzlich zum Prozessor aktivierbar ist. Dieser nimmt der
CPU die Verarbeitung von Java Bytecode ab. Er unterstützt die (allen JVMs gemeinsame)
Stackarchitektur. Ein Beispiel hierfür ist Nazomis Java Koprozessor JA108 (4k -2fach
assoziativer BytecodeCache, 2K DataCache etc).

zusätzlicher Befehlsatz
bei diesem Konzept unterstützt die CPU zusätzlich einen (Java-VM) Befehlssatz, wodurch
durch einfaches umschalten die CPU zu einer Java Virtual Machine wird. Ein Beispielt hierfür
ist ARM's Jazelle Technologie, die in den ARMxxJx Prozessoren zum Einsatz kommt.

'reine' Java Prozessoren
diese sollen nun näher untersucht werden

                                           Seite 2/ 31
Einsatzgebiete

Der Einsatz von Java-Prozessoren ist in vielen Bereichen möglich. Insbesondere eignen sie
sich in ressourcenkritischen Umgebungen wie z.B: in embedded Systems, Mikrokontroller, in
in denen die Java Features genutzt werden sollen.

   -   SmartCards                                        -   Mobiltelefone

   -   pagers                                            -   Drucker

   -   SetTop Boxen                                      -   Navigations Systeme

   -   PDA‘s                                             -   IP-Phones, IP-TV, etc

Die meisten dieser Systeme arbeiten mit weniger als 100MHz Taktfrequenz und 2 MB
Speicher, wodurch Leistungsverbrauch und Hauptspeicherverwendung schnell zu Knock-out
Kriterien bei Java Prozessoren werden.

Vergleich: Java Virtual Machine – Java Prozessor

Eine Java Virtual Machine bekommt den, von einem Java Compiler erzeugten Bytecode
übergeben. Dieser ist hardwareneutral, für die VM geschrieben, welche dem Compiler
gegenüber einen Prozessor emuliert. Die VM wandelt den erhaltenen Code in native
Instruktionen des jeweiligen Prozessors fü den sie gebaut ist. Die VM bietet auf jedem
System eine immer gleiche Schnittstelle für den Compiler, eben eine abstrakte, eine virtuelle
Maschine (write once, run anywhere).

Ein Java Prozessor bekommt (genau wie die JVM) eine class Datei mit Bytecode als Input.
Er führt diesen gemäß der JVM Spezifiaktion aus - muss nach aussen genau wie die JVM
funktionieren, ist jedoch um Funktionen zur Hardwareverwaltung und zur Ausführung nativer
Anweisungen, z.B: in C erweitert.

Wie bereits angedeutet ist der Java Prozessor eine Hardware Java 'Virtual' Maschine

                                           Seite 3/ 31
Übersicht: Java Prozessoren Context

(Sun’s) Java Prozessor Context besteht neben der Spezifikation –picoJava- aus zwei
Mikroprozessorlinien – microJava und ultraJava:

picoJava:

picoJava (picoJava Core Specification ) ist die Spezifikation für einen minimalen Java
Prozessor. Die Java Prozessor Linien von Sun basieren auf dieser Spezifikation. Und da die
picoJava Technology Lizenz anderen Chip-Herstellern zur Verfügung gestellt wird, dient
picoJava auch diesen Prozessoren als Grundlage. Lizenznehmer von picoJava sind unter
anderen Firmen wie Fujitsu und IBM . picoJava ist speziell für den Einsatz in Mobiltelefonen,
PDA`s, Set-Top-Boxen und anderen Kleingeräten ausgelegt.

microJava:

ist die 'customized Version' und der erste real existierende Mikroprozessor von Sun.
MicroJava erweitert picoJava um anwendungsspezifische E/A, sowie Speicher-,
Kommunikations- und Steuerfunktionen. Der Preis von microJava liegt zwischen 25 und 100
Dollar, was microJava für den Einsatz in einer Vielzahl von elektronischen Geräten, der
Telekommunikation und anderen nicht vernetzten Anwendungen wie Drucker, Spielkonsolen,
etc. auszeichnet.

ultraJava:

ist Sun’s High-End-Java-Prozessor. ultraJava unterstützt Sun`s Visual Instruction Set (VIS),
einer performanten Hardwaregraphikerweiterung. Die ultraJava Prozessorlinie zielt
hauptsächlich auf High-End-3D-Graphik- und Multimediaanwendungen ab. Der Preis liegt
bei >= 100 Dollar.

Pico Java
Die Spezifikationeines Java Prozessors, picoJava soll nun näher untersucht werden.

Da wie bereits erwähnt der Java Prozessor eine Implementierung der JavaVirtualMachine
plus Erweiterungen zur Hardwarekonrolle ist, mag einiges aus der Darstellung der J-VM
bereits bekannt sein.

                                           Seite 4/ 31
Zunächst Darstellung der JVM, sofern sie von picoJava implementiert ist

Überblick
Durch die Spezialisierung des Prozessors auf die Sprache Java können beim Entwurf
bereits Optimierungen entwickelt werden, die zu einer Leistungssteigerung führen.

Besonderheiten sind z.B. die stack-basierte Verarbeitung von Bytecode und die
Speicherbereinigung (GC). In picoJava wird daher statt eines frei wählbaren Registersatzes
ein Stackregistersatz mit 64 Einträgen genutzt.

Die virtual machine (im folgenden VM genannt) ist eine 32-Bit Stack-Architektur. Das
bedeutet, Operanden einer Instruktion werden vorher, z.B. durch LOAD/STORE, auf den
Stack geholt, durch die Instruktion bearbeitet und das Ergebnis wird wieder auf dem Stack
abgelegt, wo es dann für weitere Operationen zur Verfügung steht. Der Stack ist in Analogie
zu einer Registerdatei aus der RISC-Architektur zu sehen, denn Operationen können nur
Objekte auf dem Stack referenzieren.

Ein weiteres Merkmal aus der herkömmlichen RISC-Architektur ist der Speicherzugriff, der
bei der VM nur durch LOAD´s/STORE´s möglich ist. Die einzige Ausnahme hierbei stellt die
IINC-Instruktion dar, die einen Speicher-zu-Speicher Zugriff darstellt, und vornehmlich zum
Inkrementieren von Schleifenvariablen gedacht ist.

Die VM hält eine Reihe von Registern, die meist zur Kontrolle spezielle Funktionen im Core
dienen oder die Adressen verschiedener Bereiche im Stack (Stackpointer) enthalten.

Darüber hinaus besitzt die VM noch vier (general purpose) 32-Bit Register und zwar:

   -   PC (program counter)

   -   VARS (points to base of the current set of local variables)

   -   OPTOP (current top of evaluation stack)

   -   FRAME (points to the base of the current execution environment in memory).

                                           Seite 5/ 31
Speicher der Laufzeit Umgebung

Der Prozessor einer (virtuellen) Java Machine
ist wie erwähnt eine Stackmaschine mit
mehreren Stacks1 -jeweils ein JVM Stack
pro Thread 2- und dem, von allen Threads
gemeinsam genutzen Heap.

Im Heap werden sämtliche Objekt-Instanzen
sowie Klassen und Interfaces abgelegt,
wobei sich Interfaces noch einmal in einem
speziellen Bereich, der sog. Method Area
befinden. Der Heap wird durch den Garbage
Collector automatisch verwaltet / bereinigt.

Zur Verwaltung von Prozeduraufrufen und Rücksprungadressen dient der Aufruf-Stack. Er
enthält Frames (Aktivierungssätze), die bei jedem Unterprogrammaufruf erzeugt, auf dem
Aufruf Stack abgelegt werden und die nötigen Rücksprungadressen, Zellen für lokale
Variablen, Parameter, Operanden etc. enthalten.

Der JVM-Stack ist eine Vereinigung von Aufruf- und Operanden Stack (s.u.)

Zu jedem Stack existiert ein PC Register (Programmzähler), das auf die Adresse des gerade
ausgeführten Codes verweist.

Der class-constant-pool ist der Daten- und Codebereich eines Java Programms

Mikroarchitektur

E/A Bus- und Speicherschnittstelle

stellt die Schnittstelle zwischen dem
picoJava Kern, dem externen Speicher
und anderen E/A-Geräten dar. Sie
nimmt Daten an und liefert diese an den

1
    hat den Vorteil eines kompakteren Befehlssatzes, da Operanden weggelassen werden können (Operanten
Stack)
2
    für Aufrufe nativer Methoden kann es dazu noch einen Native-Stack pro Thread geben

                                                    Seite 6/ 31
Instruktions- und den Datencache weiter.

Datencache

besteht aus dem, in seiner Größe konfigurierbaren 3 Datencache und dem Datencache-
Kontroller. Die Datencache-Einheit arbeitet die Anfragen des Dripple Managers (s. u.) und
der Pipeline ab.

Instruktionscache

besteht aus dem, in seiner Größe3 konfigurierbaren Instruktionscache und dem
Instruktionspuffer. Die Instruktionscache-Einheit speichert hereinkommende Instruktionen
und hält sie solange, bis sie der Dekodierblock der Integer-Einheit abholt. Um den Rest der
Pipeline von der Fetch-Stufe zu trennen, wird ein 16 Byte Instruktionspuffer benutzt, der die
Instruktionen solange im Speicher hält, bis sie von der Integer-Einheit verarbeitet werden
können.

Stackcache

ist für die Kommunikation zwischen Stack und Integer-Einheit (Operanden) verantwortlich
und kontrolliert Lesen bzw. Schreiben von Daten zwischen Datencache und Stackcache. Der
Dribble Manager (to dribble = tröpfeln) sorgt bei Über- bzw. Unterlauf des Stackcaches für
ein Herausschreiben in den Datencache bzw. für Datennachschub (s.u.).

Integer-Einheit

ist der „Pförtner“ für alle Instruktionen. Sie holt Instruktionen aus der Instruktionscache-
Einheit, leitet Floating-Point-Instruktionen an die Floating-Point-Einheit weiter, führt alle
Nicht-Floating-Point Instruktionen der JVM und die erweiterten Bytecodes (s.u.) aus, und holt
bzw. speichert Daten aus/in der Datencache-Einheit. Die Floating-Point-Einheit führt alle
mathematischen Funktionen aus. Sie ist optional.

3
    auf 0kb, 1kb, 2kb, 4kb, 8kb, 16kb

                                             Seite 7/ 31
Pipeline

Sun nutzt eine RISC-ähnliche Pipeline für picoJAVA. Sie hat nur 4 Stufen: Fetch, Decode,
Execute und Writeback.

Zugriffe auf den Cache (nie auf den Hauptspeicher) finden während der Execute Phase statt.
(Stack-basierte Architekturen greifen nach einer LOAD-Instruktion immer auf die durch das
LOAD gelieferten Daten zu -> Zugriff auf das Data Cache ist nicht “pipelined”).

                                          Seite 8/ 31
der Befehlssatz

Jede Anweisung der Java VM besteht typischerweise aus einem ein Byte großem Opcode
(256 Instruktionen) plus null oder mehreren Operanden (verschiedener Länge). Die Anzahl
oder Größe der Operanden wird dabei implizit durch den Opcode bestimmt.

Da der Befehlssatz Java's stackbasiert ist, werden bei vielen Befehlen die Operanden vom
Stack geholt und das Ergebnis wieder auf den Stack gelegt. Diese Befehle brauchen keine
zusätzlichen Bytes für Operanden und haben somit eine Länge von einem Byte.

Befehle mit Operanden haben dagegen eine Länge von zwei, der oder mehr Bytes (s.u.
Fehler! Verweisquelle konnte nicht gefunden werden.)

Beispiel:

iadd definiert eine Integer-Addition komplett, es muss nicht explizit angeben werden was
addiert, oder wo das Ergebnis abgelegt werden soll. Die zwei obersten Elemente werden
vom Stack geholt, addiert und das Ergebnis wieder zurück auf den Stack gelegt.

 Befehlsfomat

Der Befehlssatz der JavaVM ist TYPISIERT, d.h. für jeden Operandentyp gibt es einen
speziellen Befehl (z.B. Addition von Integer-Zahlen: iadd). Sind Operanden länger als ein
Byte, werden sie in einer "Big-endian"-Order gespeichert.

                                          Seite 9/ 31
opcode      byte      short     int                long      float     double    char      reference

Tipush      bipush    sipush

Tconst                          iconst             lconst    fconst    dconst              aconst

Tload                           iload              lload     fload     Dload               aload

Tstore                          Istore             lstore    fstore    dstore              astore

Tinc                            Iinc

Taload      baload    saload    iaload             laload    faload    daload    caload    aload

Tastore     bastore   sastore   iastore            lastore   fastore   dastore   castore   aastore

Tadd                            iadd               ladd      fadd      dadd

Tsub                            isub               lsub      fsub      dsub

Tmul                            imul               lmul      fmul      dmul

Tdiv                            idiv               ldiv      fdiv      ddiv

Trem                            irem               lrem      frem      drem

Tneg                            ineg               lneg      fneg      dneg

Tshl                            ishl               lshl      fshl      dshl

Tshr                            ishr               lshr

Tushr                           iushr              lushr

Tand                            iand               land

Tor                             ior                lor

Txor                            ixor               lxor

i2T         i2b       i2s                          i2l       i2f       i2d

l2T                                                l2i       l2f       l2d

f2T                                                f2i       f2l       f2d

d2T                                                d2i       d2l       d2f

Tcmp                                                         lcmp

Tcmpl                                                        fcmpl     dcmpl

Tcmpg                                                        fcmpg     dcmpg

if_TcmpOP                       if_icmpOP                                                  if_acmpOP

Treturn                         ireturn            lretrun   freturn   dreturn             areturn

                                          Seite 10/ 31
Funktionale Gruppierung

Die 226 Befehle der JVM können in 15 funktionale Gruppen aufgeteilt werden. Um die
decodierung möglichst effizient zu halten, bzw. um geringe Codedichte zu gewährleisten gibt
es variable Codelängen, wobei häufig genutzte Instructions kürzer sind. Die Meisten
Instruktionen (62%) sind 1 Byte groß. Die restlichen Befehle sind zumeist 2 Byte (20%) oder
3 (15%) Byte lang. Nur 6 Befehle (3%) sind größer als 3 Byte. Die durchschnittliche
Befehlslänge beträgt 1,8 Byte (14-15 Bit).

Befehlstyp                            Gesamtzahl       Anzahl von Befehlen mit der Länge:

                                                            1 Byte   2 Bytes   3 Bytes   Mehr als 3 Bytes
Konstante auf Stack legen                   13                 8        2         3              -
Laden/Speichern lokaler Variabeln           82                40        41        1              -
Stackverwaltung                             10                10         -         -             -
Arithmetik                                  24                24         -         -             -
Schiebe- und Logikoperatoren                12                12         -         -             -
Verzweigungen und Vergleiche                27                 5        1         19            2
Ausnahmebehandlung                          1                  1         -         -             -
Arrayverwaltung                             20                17        1         1             1
Methodenrücksprünge                         7                  7         -         -             -
Switch-Table Verzweigungen                  2                  -         -         -            2
Konvertierungen                             15                15         -         -             -
Monitore                                    2                  2         -         -             -
Änderungen von Objektfeldern                4                  -         -        4              -
Methodenaufrufe                             4                  -         -        3             1
Sonstige Objektbehandlung                   3                  -         -        3              -
Gesamtzahl                                 226               141        45        34            6
Anteil (in %)                              100                62        20        15            3

226 Instruktionen:

      -    141 Instruktionen 1 Byte Länge (62%)

      -     45 Instruktionen 2 Byte Länge (20%)

      -     34 Instruktionen 3 Byte Länge (15%)

      -      6 Instruktionen >3 Byte Länge (3%)

Vergleicht man den Befehlssatz von Java z. B. mit dem eines RISC-Prozessors, erscheint
der Befehlssatz von Java unvollständig. Es fehlen beispielsweise Befehle, die mit den Zielen
von Java nicht vereinbar sind. Das JSM4 zum Beispiel fordert z.B., dass es für den
Programmierer nicht ersichtlich sein soll, wo Objekte im Speicher liegen. Deshalb ist es mit
Java-Instruktionen nicht möglich direkt und willkürlich auf den Speicher zuzugreifen. JVM-

4
    JSM – Java Security Model

                                             Seite 11/ 31
Instruktionen arbeiten stattdessen auf (dem Datentyp) Objektreferenzen, der keine
Rückschlüsse auf die tatsächliche Position der Objekte im Speicher zulässt. Der Speicher ist
für den Java Programmierer wie eine Black-Box. Es ist die Aufgabe der JVM die Position der
referenzierten Objekte im Speicher zu bestimmen.

Befehle, die man im Befehlssatz von Java außerdem vermisst sind Befehle zur
Hardwarediagnose oder zu low-lewel Hardwaremanagement, Befehle um den CPU-Status
zu lesen oder zu schreiben oder die On-Chip-Caches zu verwalten. Diese Befehle haben im
Befehlssatz von Java keinen Platz, weil sie von der Beschaffenheit der Hardware abhängen.
Außerdem sollte picoJava auch mit Code umgehen können der nicht in Java gechrieben
wurde (z.B. C oder C++).

Im Befehlssatz der JVM fehlen also Befehle, die für einen real existierenden Prozessor
unabdingbar sind. Da man den Befehlssatz nicht einfach verändern kann, ohne damit auch
Java zu verändern, hat man in picoJava den Java Befehlssatz erweitert.

 erweiterte Bytecodes

Die folgende Tabelle fasst die 115 Befehle, um die der Befehlssatz der JVM erweitert worden
ist, in fünf funktionalen Gruppen zusammen:

            Befehlstyp              Gesamtzahl Anzahl von Befehlen mit der Länge:
                                                          1 Byte   2 Bytes   3 Bytes
Diagnose                                 8                   -        8         -
Lesen/Schreiben von Registern            49                  -        49        -
Beliebiges Laden/Speichern               35                  -        26        9
Unterstützung anderer                    6                   -        5         1
Programmiersprachen
System Software Unterstützung             17                2        10        5
Gesamtzahl                               115                2        98        15
Anteil (in %)                            100                2        85        13

Für die technische Realisierung dieser Erweiterung stellte sich als Problem:

Mit einem Opcode von 8 Bit wie ihn die JVM verwendet, können maximal 28=256
Instruktionen codiert werden. Die Basis Instructions belegen 226 Instruktionen, also ist für
weitere 30 Befehle noch Platz.

picoJava benötigt allerdings 115 weitere Befehle. Dieses Problem wird durch so genannte
Escape Bytes gelöst.

                                           Seite 12/ 31
Beim Design der JVM wurden zwei Bytes für implementations-spezielle Angelegenheiten
reserviert. Eines dieser zwei Bytes wird als Escape Byte definiert. Stößt die picoJava-
Dekodierlogik beim Dekodieren eines Befehls auf dieses Escape Byte, so weiß sie, dass es
sich bei diesem Befehl um einen erweiterten Befehl handelt, da diese Bytekombination von
der JVM ja nicht benutzt wird. Die Dekodierlogik schaut dann auf das zweite Byte, um
herauszufinden um welchen Befehl es sich handelt, bzw. was dieser Befehl macht.

Diese 341 Instruktionen, die 226 Basis-, und 115 erweiterten Befehle ergeben den
kompletten Befehlssatz von picoJava.

Der Befehlssatz von picoJava kann nun nicht nur alles was die virtuelle Maschine kann,
sondern noch mehr. picoJava kann Hardware kontrollieren, kann auf Speicher zugreifen und
es kann effizient Code ausführen, der nicht in Java geschrieben wurde.

Dadurch ist der Befehlssatz von picoJava ist nicht mehr länger der Befehlssatz einer Virtual
Machine, es ist der komplette Befehlssatz einer reellen Maschine.

Per Definition kann kein Programm, das in Java geschrieben und auf herkömmlichem Wege
in Bytecode kompiliert wurde, erweiterte Bytecodes enthalten. Oder anders: Ein Programm,
das erweiterte Bytecodes enthält kann kein normal kompiliertes Java Programm sein.

Stattdessen sind die erweiterten Bytecodes von picoJava für Programme da, die nicht in
Java, sondern z.B. in C oder C++, geschrieben wurden und auf picoJava portiert werden
sollen. Da nur Plattformen, die auf picoJava basieren die erweiterten Bytecodes verstehen,
läuft ein Programm, das erweiterte Bytecodes enthält nicht auf anderen Plattformen. Und da
einige der erweiterten Bytecodes Programme ermöglichen, die direkten Zugriff auf den
Speicher haben – und damit das JSM unterlaufen – kann kein Programm, das erweiterte
Bytecodes enthält ( im Sinne des JSM ) als sicher bezeichnet werden. Nicht-Java-Code, der
auf einem Java-Prozessor läuft, verhält sich also genau wie Nicht-Java-Code, der auf einem
anderen Prozessor läuft, er ist plattformabhängig und nicht sicher.

Ein RISC-Prozessor, hat ca. 100 Befehle. Der Befehlssatz von picoJava hat mit seinen 341
Befehlen mehr als drei Mal so viele Befehle. Um mit dieser Menge an Befehlen effektiv
arbeiten zu können, wurden die Befehle in drei Gruppen eingeteilt.

                                           Seite 13/ 31
Komplexität Handhaben - Gruppierung nach Komplexität

picoJava ist speziell für den Einsatz in eingebetteten Systemen gedacht, und soll deshalb
klein und preiswert sein. Dieses Ziel steht in Konflikt mit dem großen Befehlssatz von
picoJava.

picoJava's Designer lösten dieses Problem, in dem sie nach der 'Schwierigkeit Befehle zu
implementieren' die Instructions in drei Gruppen einteilten: einfache, relativ schwierige und
sehr schwierige Befehle.

Einfache Instruktionen:

In diese Kategorie fallen die meisten Befehle der JVM und auch die meisten der erweiterten
Befehle. Die Befehle dieser Kategorie sind RISC-ähnlich in dem Sinne, dass sie 'hardwired' –
hart verdrahtet sind. Sie werden in nur einem Taktzyklus ausgeführt.

Beispiele für solche Instruktionen sind „quick load“ von Objektfeldern und alle Integer
Arithmetikoperationen.

einfach (RISC) 1

       Kürzel          Operanden        Opcode            Funktion

       iadd                             0x60              Ganzzahl Addition

       iload           8 bit O_set      0x15              lade lokale Variable(Ganzzahl)

       fload           8 bit O_set      0x17              lade lokale
                                                          Variable(Flie_komma.)

       bipush          8 bit Konst.     0x10              lege eine Byte-Konstante ab

       ifeg            16 bit O_set     0x99              Springe, wenn 0

Relativ schwierige Instruktionen:

In diese Kategorie fallen ca. 30 der Befehle der JVM und die restlichen der erweiterten
Befehle.

In einem typischen Java-Programm kommen wenige Befehle dieser Kategorie vor. Diese
Befehle sind eher CISC-ähnlich in dem Sinne, dass sie Komplexität im 'Cisc-Style'
handhaben – durch Mikrocode. Vom Hardware -Standpunkt gesehen, sind die Kosten von

                                           Seite 14/ 31
Microcode relativ gering. Ein kleiner Mikrocode-ROM kann die nötigen Kontrollsignale für
diese Instruktionen enthalten. Der picoJava Kern benützt zwei ungefähr 2 Kilobyte große
ROMs: einen in der Integer Einheit und einen in der optionalen Floating-Point-Einheit.

Mikrocodierte Instruktionen benötigen zwischen 3 (z. B. iaload) und 21 (z.B.
invokesuper_quick) Taktzyklen. Sie bieten eine akzeptable Balance zwischen der
Notwendigkeit die Hardwareimplementation einfach zu halten und guter Performance.

komplex (Cisc) 1

                   Lookupswitch – Java Switch Anweisung:

                   byte 1         byte 2             byte 3       byte 4

                   opc. 0xAB      0..3 bytes padding

                   default - standard Sprungaddresse

                   Anzahl der Vergleichswerte

                   Vergleichswert 1

                   Sprungaddresse fur Wert 1 •

                   Vergleichswert 2

                   Sprungaddresse fur Wert 2 •

                   ...

Sehr schwierige Instruktionen

In diese Kategorie fallen die letzten 30 Befehle der JVM. Die Instruktionen in dieser
Kategorie sind entweder sehr schwierig, oder benötigen Dienste vom Betriebssystem, oder
beides.

Zum Beispiel treffen auf den Befehl new, der zur Erzeugung neuer Objekte benutzt wird,
beide Fälle zu: Er ist relativ schwierig, da nachgeschaut werden muss, ob die Klasse des
neuen Objekts in der Liste der bereits geladenen Klassen existiert und es muss Speicher
allozeiert werden, was eine Koordination mit Betriebssystem und eine gewisse Flexibilität in
der Art wie diese Allokation implementiert ist erfordert. Außerdem muss die neue Klasse,
wenn sie bisher noch nicht geladen wurde, über ein Netzwerk oder das lokale Filesystem
geladen werden.
                                           Seite 15/ 31
Da die Instruktionen in dieser Kategorie also entweder sehr komplex sind und/oder eine
flexible Im plementierung (wegen ihrer Abhängigkeit vom Betriebssystem) benötigen, sind sie
in Software implementiert. Wenn ein Programm einen dieser Bytecodes erfordert, ruft die
CPU einen sog. 'instruction emulation' Trap (IET). Abhängig davon welcher Bytecode die IET
ausgelöst hat, ruft der Exception-Handler eine spezielle Softwareroutine auf, welche die
getrappte Instruktion durch eine Abfolge von mikrocodierten und hart-verdrahteten
Instruktionen abarbeitet.

Eine solche Verarbeitung von Instruktionen durch Software ist natürlich sehr langsam: Eine
Instruktion dieser Kategorie benötigt mehrere hundert-, bis sogar mehreren tausend
Taktzyklen. Al lerdings werden diese Instruktionen auch von Interpretern oder dynamischen
Compilern anderer Prozessoren durch ähnliche Sequenz kleinerer Routinen ausgeführt.
picoJava hat hier also im Vergleich keinen Nachteil. Im Gegenteil, ist picoJava im Vergleich
zu anderen Prozessoren bei der Ausführung im Vorteil da die emulations Routinen nicht nur
über HardwareTraps sehr schnell erreichbar, sondern auch bereits vorgeladen sind.

Befehle dieser Kategorie kommen -im Vergleich zu Befehlen der anderen Kategorien- in
einem typischen Java-Programm jedoch nicht oft vor.

           Kürzel           Operanden Op-Code            Funktion

           instanceof       Klasse 16b. 0xC1             Klassenzugehörigkeit

           athrow                        0xBF            Ausnahmebehandlung

           new              Klasse 16b. 0xBB             ein neues Objekt

           newarray         atype 8b.    0xBC            eine neue Tabelle

           monitorenter                  0xC2            Erwerben der Kontrolle
                                                         über ein Objekt

           monitorexit                   0xC3            Abgeben der Kontrolle

Stackorganisation
Wie bereits beschrieben ist die JVM und damit auch picoJava / der Befehlssatz von
picoJava stackbasiert.

Dies bedeutet, dass bei vielen Befehlen implizit angenommen werden kann, dass
Operanden vom Stack geholt und das Resultat des Befehls wieder auf den Stack gelegt
wird. Ein stackbasierter Befehlssatz ermöglicht kleine, sichere und portable Programme, hat
                                          Seite 16/ 31
aber den Nachteil, dass stackbasiertes Verarbeiten von Befehlen sehr ineffizient ist. Eine
Stackmaschine benötigt Zeit (Taktzyklen) um Operanden auf den Stack zu legen, wo
Rechenoperationen sie dann verarbeiten können. Nachdem die Rechenoperationen ihr
Ergebnis wieder auf den Stack gelegt haben, benötigt die Stackmaschine wieder Zeit um die
Resultate vom Stack zu nehmen und sie abzuspeichern. Eine Registermaschine braucht
keine Zeit um Operanden hin und her zu bewegen, da hier direkter Zugriff auf die jeweiligen
Register möglich ist.

Im Vergleich zu Registermaschinen benötigen Stackmaschinen für die gleiche Anzahl von
Berechnungen 30 Prozent mehr Operationen 5 (durch die zusätzlichen Stackzugriffe).

Beispiel / Vergleich:

      Registerbasierte Addition                                       Stackbasierte Addition

      ADD R3, R2, R1                                                  ILOAD_1 ILOAD_2 IADD ISTORE_3

      Bei einer registerbasierten RISC-Maschine Die stackbasierte Addition benötigt vier
      kann eine Addition in einer einzigen                            Instruktionen, die jeweils einen Taktzyklus
      Instruktion ausgeführt werden. In den                           benötigen. Die ersten beiden Befehle
      Registern R1 und R2 sind die beiden                             bewegen die Summanden zum Stack.
      Summanden gespeichert, während im                               Diese werden mit dem dritten Befehl
      Register R3 die Summe gespeichert                               addiert. Das Resultat wird dann schließlich
      werden soll. Die Operation kann in einem                        mit dem vierten Befehl       wieder
      Taktzyklus ausgeführt werden.                                   abgespeichert.

Wie ist dies aufzulösen?

picoJava hat bereits einen stackbasierten Befehlssatz, ein registerbasierter Befehlssatz
kommt also nicht mehr in Frage. Trotzdem wollte man auf die Effizienz einer
Registermaschine nicht verzichten. Die Lösung dieses Problems ist eine Registermaschine,
die so organisiert ist, dass sie ein stackbasiertes Verarbeiten der Befehle unterstützt.

5
    W. Wulf et al., 'The Design of an Optimizing Compiler', American Elsevier, New York, 1973.

                                                               Seite 17/ 31
picoJava's Stackorganisation 1

Die picoJava Registermaschine hat 64 Register, welche genutzt werden um die obersten 64
Einträge des Stacks zu cachen.

picoJava behandelt diese Register als „circular Buffer“, was bedeutet, dass das unterste
Element und das oberste Element im Stack benachbart sind.

picoJava hält sich einen Zeiger auf das oberste Element im Stack. Wenn die
Ausführungseinheit Elemente vom Stack holt, schrumpft der Stack und der StackPointer wird
inkrementiert. Wenn die Ausführungseinheit dagegen Elemente auf den Stack legt, wächst
der Stack und der Pointer wird dekrementiert. Wie die meisten Stacks wächst der picoJava
Stack von höherwertigen Adressen zu niederwertigeren. Legt man 65 Elemente auf den
Stack, überschreibt dies das erste Element im Stack. Hier ist dann der DribbleManager
gefordert .

Die Registermaschine hat drei Lese- und zwei Schreibports. Rechenoperationen können
gleichzeitig zwei Operanden lesen und ein Resultat zurück schreiben. Die restlichen Ports
(ein Lese- und ein Schreibport) belegt der Dripple Manager, der durch ständige im
Hintergrund laufende Spill- und Fill-Operationen 6 den Stackcache konsistent hält.

6
    Spill – schreibt Einträge vom Register File in den Datencache un schafft so Platz für neue Werte

                                                                Seite 18/ 31
High- und Low Watermarks

Einträge, die noch nicht in den Datencache
geschrieben wurden, werden als 'dirty'
bezeichnet. Überschreitet bei wiederholtem
Ablegen von Elementen auf dem Stack die
Anzahl der 'dirty' Einträge eine obere Grenze
(High-Water-Mark), schreibt der Spill-
Mechanismus (im Hintergrund) diese Einträge
in den Datencache heraus – beginnend mit dem Ältesten. Bereits in den Cache kopierte
Werte werden als 'clean' betrachtet.

Obwohl der Stackcache nur 64 Einträge hat können - indem clean'e, bereits in den
Datencache geschriebene Werte überschrieben werden - viel mehr Elemente auf dem Stack
liegen.

Wenn dagegen der Stack durch mehrmaliges auslesen von Daten schrumpft und unter die
untere Grenze (Low-Water-Mark) fällt, holt der Fill-Mechanismus des Dripple-Managers (im
Hintergrund) Einträge aus dem Datencache und füllt den Stack damit wieder auf.

Die Spill- und Fill-Mechanismen erwecken so den Eindruck, dass der Stackcache eine
unendliche Anzahl von vollen Registern hat, die belesen und beschrieben werden können.

Eine der wichtigsten Merkmale des picoJava Caches ist, das er eine Lösung für das
klassische Problem des ineffektiven Stackzugriffs anbietet.

Instruction Folding

Zusammenfassen von Befehlen

Da der Stack in Wirklichkeit ein Register File mit Random Access ist, hat picoJava's Pipeline
nicht nur direkten Zugriff auf die obersten zwei, sondern auf die obersten 64 Stackelemente,
was das Instruction Folding – das Zusammenfassen von Instruktionen – ermöglicht.

Dabei geht picoJava folgendermaßen vor:

Basierend auf folgenden Gruppierungsregeln scannt picoJava's Instruction Decoder den
eingehenden Bytecode-Strom und untersucht ihn nach Befehls-Sequenzen, die zu einer

Fill – liest Einträge vom Datencache in das Register File und sorgt so für die nächsten Berechnungen vor

                                                             Seite 19/ 31
einzelnen Instruktion zusammengefasst werden können. Diese zu 'faltenden' Sequenzen
können innerhalb von bis zu 4 Bytecode Instructions

   -   lokale Daten direkt vor den Rechenoperationen die diese Daten nutzen oben auf den
       Stack bewegen und/oder

   -   Berechnungen direkt gefolgt vom lokalen Speichern der Berechnungsresultate
       enthalten.

Wenn solch eine Sequenz gefunden wird, erzeugt der Core daraus eine einzelne, Register-
basierte RISC-artige Operation, indem die

   -   auszuführende Rechenoperation und

   -   ihre Operanden, sprich

           o   die Adresse der lokalen zu ladenden Variablen (Quellregister) und

           o   die Adresse der lokal zu Speichernden Variablen (Zielregister)

kombiniert werden.

Einfacher gesagt, kombiniert picoJava die in Stackarchitekturen für eine Rechenoperation
nötigen zusätzlichen Stackmanipulationen mit der Rechenoperation selbst. Dies vermindert
den rechentechnischen Overhead einer Stackmaschine für die 'gefalteten' Operationen
drastisch. Es wird eine 'Single Cycle' Execution erreicht und damit die, von der Risc
Architektur bekannte Effektivität bei der Ausführung, da sich unter der Stackarchitektur eine
Risc ähnliche Architektur komplett mit einem 64 Einträge großen Register-File und '3
Operanden, register-basierten' Operationen befindet.

Beispiel: Instruction folding

Das, aus dem Abschnitt 'Stackorganisation' bereits bekannte Beispiel :

                                                  ILOAD_1
                                                  ILOAD_2
                                                  IADD
                                                  ISTORE_3

iload_1 und iload_2 bewegen lokale Daten auf den Stack. Darauf folgt direkt die
Rechenoperation iadd, die nur die bewegten Daten benutzt. Dies ist Gruppierungsregel 1.

                                            Seite 20/ 31
Mit istore_3 wird das Resultat aus iadd lokal abgespeichert. Dies ist Gruppierungsregel
2. Damit können diese vier Befehle zu einem Befehl der Art ADD R3, R2, R1
zusammengefasst werden. R1 ist der, mit iload_1 auf den Stack bewegte, erste
Summand, R2 ist der, mit iload_2 bewegte, zweite Summand und R3 ist das Register, zu
der istore_3 die Daten bewegt. Der zusammengefasste Befehl benötigt statt vier nur noch
einen Taktzyklus.

Hardwareunterstützung der Laufzeitanforderungen

Um die Ausführung von Java Programmen zu beschleunigen, wurde beim Entwurf von
picoJava darauf geachtet, dass bestimmte Laufzeit-Anforderungen von Java Programmen,
wie zum Beispiel die Thread-Verwaltung, das Object-Handling, und die Garbage Collection,
durch die Hardware unterstützt werden.

Dies soll für den Garbage Collection Mechanismus näher untersucht werden

                                         Seite 21/ 31
Garbage Collection

Wie erwähnt, fordert das JSM, dass es nicht ersichtlich ist, wo Objekte im Speicher liegen.
Ein Java Programm kann nur über Objektreferenzen 7 die keine Rückschlüsse auf die
tatsächliche Position der Objekte zulassen, auf den Speicher zuzugreifen. Ein Java
Programm kann also selbst keine Speicherverwaltung durchführen -diese Aufgabe
übernimmt die JVM: Sie verwaltet den Speicher eines Programms automatisch, in dem sie
dynamisch Speicherbereiche auf dem Heap alloziert, wenn er benötigt wird und ihn wieder
frei gibt, wenn er nicht mehr benötigt wird. Der von der JVM verwendete Mechanismus zur
Speicherverwaltung ist Garbage Collection.

Die JVM hat einen HEAP Bereich, in dem Objektinstanzen, Klassen u. Interfaces liegen (s.o.
[Speicher der Laufzeit Umgebung]) Heap ist der einzige Speicherbereich, der durch
automatische Speicherbereinigung (GC) verwaltet wird.

Neben der Bytecode-Ausführung ist der andere entscheidende Aspekt für die Performance
einer VM die Garbage Collection. Weder in der Java Sprachspezifikation noch in der Java
VM Spezifikation sind jedoch genaue Vorgaben für die Garbage Collection zu finden. Es
steht den Herstellern somit größtenteils frei, wie sie die Speicherverwaltung implementieren.

picoJava's Garbage Collection Mechanismus ist ein Zusammenspiel der folgenden
Verfahren

    Mark & Sweep (markieren und rausschmeissen)

Eine der einfachsten Formen der Garbage Collection ist der sogenannte Mark & Sweep-
Algorithmus. Bei diesem Verfahren wird ein Speicherbereich periodisch nach Objekten
durchsucht, die von laufenden Programmen aus noch erreicht werden können. Die so
gefundenen Objekte werden mit einem Bit markiert. Wenn alle noch erreichbaren Objekte
markiert wurden, kann vom restlichen Speicher – in dem evtl. noch nicht erreichbare
Objekte liegen – angenommen werden, dass dieser frei ist. Der Garbage Collector geht dann
den Speicher durch, merkt sich allen freien Speicher und fügt ihn wieder zum „freier Speicher
Pool“ hinzu. Um eine Fragmentierung des Speichers zu verhindern ist der letzte Schritt
dieses Verfahrens, dass der freie Speicher und auch die noch referenzierten Objekte zu
gemeinsamen Blöcken zusammengeführt werden.

7
    Datentypen der Java VM: byte, short, int, long, float, double, char, object, returnAddress

                                                       Seite 22/ 31
Während dieses Verfahrens (Aufräumen & Zusammenführen) befindet sich das System in
einem instabilen Zustand, da, wenn der Prozess einmal begonnen hat er nicht unterbrochen
werden darf. Dies führt zu merklichen Performanceeinbußen.

Zum Markieren der Daten (referenziert/nicht referenziert) werde die, in den Datentypen
Zeiger/Reference und Object für Software Zwecke reservierte Bits genutzt (Bits 30, 31)

Diese gibt’s es sowohl im Typ Zeiger (Reference) als auch im Header eines Objekts für
Softwarezwecke.

Handles
Das Verschieben von Objekten im Speicher wird durch sog. Handles unterstützt. Es wird
zwischen direkten Referezen -Zeiger- und indirekten Referenzen –Handles– unterschieden.
Dies trifft eine Aussage über die Art der Objektspeicherung.

Der 32 bit große Typ Reference (Zeiger) nutzt Bit 0 um zwischen Handle und 'nicht
Handle'zu unterscheiden. Ist der Wert von Bit 0=0 handelt es sich um eine direkte Referenz,
ist er 1 um eine indirekte.

                                          Seite 23/ 31
Objektspeicherung

An der Adresse auf die ein Zeiger verweist beginnt das Objekt im Speicher. An dieser Stelle
liegt der Objekt Header, der Methoden Vektor o.ä. enthält.

Ist ein Objekt nun in 'herkömmlicher' Weise im Speicher abgelegt liegen seine weiteren
Daten direkt hinter dem Header. Zeiger auf solche Objekte nennen sich direkte Zeiger- das
Handle-Bit ist nicht gesetzt.

Ist das Handle-Bit einer Referenz allerdings gesetzt weist das die zweite Form der
Objektspeicher hin. Hier liegt direkt hinter dem Objekt Header ein sog. Handle, ein weiterer
Zeiger der auf die Adresse verweist an der der Rest des Objekts abgelegt ist.

                                          Seite 24/ 31
Diese Form hat den Vorteil, das wenn das Objekt im Speicher verschoben wird, nur die
Handles und nicht alle vereisenden Zeiger geändert werden müssen. Sie bieten also einen
einfachen Mechanismus für den GarbageCollector Objekte im Speicher zu verschieben,
haben allerdings auch Nachteile.

Die Nutzung von Handle benötigt zusätzlichen Speicher und Ausführungszeit. Jede
Instruction die auf ein Objekt zugreift benötigt zusätzlichen Aufwand von mindestens 2
Taktzyklen um die Umleitung, die Indirektion zu handhaben. Ausserdem werden bei der
Speicherung per Handle für jedes gespeicherte Objekt ein zusätzliches Word Speicher für
den 'Object Storage Pointer' benötigt.

 Generational Garbage Collection
Bei der Generational Garbage Collection (GGC) werden die Speicherscans des Mark &
Sweep auf kleinere Speicherbereiche beschränkt. Dies erhöht die Performance der Garbage
Collection, und damit auch deren Einsetzbarkeit in Echtzeit-Umgebungen.

Generationen-Kollektoren gehen davon aus, dass einige Objekte länger leben als andere.
Weiterhin wird angenommen, dass die meisten Objekte jung sterben. Dementsprechend wird
der Heap in mehrere Überlebensräume – Generationen – unterteilt. Neue Objekte werden
grundsätzlich in der jüngsten Generation – Eden- alloziert.

Ist kein Platz mehr in Eden, greift ein kopierender Kollektor, scannt diesen Überlebensraum
und verschiebt lebendige Objekte die eine bestimmte Anzahl von Aufräumphasen überlebt
haben in den nächsten Überlebensraum (babei müssen alle Zeiger auf das Objekt
entsprechend angepasst werden).

                                           Seite 25/ 31
Räume für jüngere Generationen sind kleiner. Wenn ein Bereich ein neues Objekt nicht mehr
aufnehmen kann wird er gescannt und per mark & sweep aufgeräumt. Dies führt zu einer
höheren Scanfrequenz.

Dieser erste Überlebensraum wird mit hoher Frequenz nach nicht mehr referenzierten
Objekten gescannt, wodurch bereits die meisten „toten“ Objekte entfernt werden können.

Der nächste Überlebensraum wird seltener gescannt. Objekte, die auch hier die
Inkubationszeit überleben, werden wieder in den Bereich für die nächste Generation
verschoben und auch hier nimmt die Frequenz der Scanns wieder ab. Dieses Verfahren wird
bis zur n-ten Inkubationsstufe fortgesetzt, wobei jeweils die Scanfrequenz abnimmt. Objekte
die auch die n-te Inkubationszeit überleben, werden in den restlichen Speicher, die
permanente Generation verschoben.

Auch beim GGC-Verfahren muss ab und zu der gesamte Speicher nach nicht mehr
benötigten Objekten durchsucht werden, da die Zahl der langlebigen Objekte mit der Zeit
zunimmt und die Gefahr besteht, dass der Speicher aufgebraucht wird. Dennoch wird die
Zahl dieser zeitintensiven komplett-Scans zur Ausnahme.

Generationen optimieren also die Speicherbereinigung insofern, als dass nicht immer der
ganze Speicher aufgeräumt wird, sondern nur der Teil, der gerade vollgelaufen ist. Die
Pausen, die auftreten wenn das Programm z ur Speicherbereinigung gestoppt werden muss,
sind somit geringer als bei nur einem großen zusammenhängenden Speicherbereich, der
immer komplett gesäubert werden muss. Dabei macht man sich zunutze, dass ein kleines
Speichersegment gewöhnlich sehr schnell mit Objekten belegt ist, die zu einem großen Teil
direkt wieder aus dem Speicher entfernt werden können.

Es gibt noch weitere hochentwickelte Garbage Collection Verfahren, von denen die meisten
auch auf einer Segmentierung des Speichers beruhen. picoJava unterstützt daher die
Segmentierung von Speicher hardwareseitig durch sog. Schreibbarrieren.

                                          Seite 26/ 31
Write Barriers

Um einen bestimmtes Speichersegment zügig nach Objekten scannen zu können auf die
noch Verweise existieren, muss der GC ein Liste mit mit allen Objekten in diesem Segment ,
die von ausserhalb des Segments erreichbar sind vorhalten. Ohne eine solche Liste müsste
der GC den Rest des Speicher scannen um herauszufinden welches externe (extern des zu
scanneden Segments) Objekt noch Referenzen auf interne Objekte hält (das somit ja nicht
entfernt werden darf).

Der primäre Mechanismus um eine solche Liste zu erstellen sind sog. Schreib
Barrieren. Der Schreib-Barriere Mechnismus ermöglicht es Zeiger von Objekten die sich
ausserhalb des zu scannenden Bereichs befinden in sog. Stores vorzuhalten/zu listen um
sie effizient daraufhin zu untersuchen, ob sie auf Objekte inerhalb des zu scannenden
Segments verweisen.

In GenerationsSystemen werden diese Zeiger als 'inter generational pointers' bezeichnet.

picoJava bietet eine fleixible Methode um Segment Grenzen zu definieren.

Ist ein Segment einmal festgelegt, prüft als nächstes die Hardwe alle Zeiger in den 'Zeiger -
Stores' daraufhin, ob einer der Pointer auf ein Objekt in einem, von sich selbst
verschiedenes Segment verweist. Ist das der Fall so wird eine Unterbrechung, ein 'Trap'
ausgelöst 8 und der GC kann entsprechend reagieren, was hier bedeutet die Referenz in
seine entsprechende Liste aufzunehmen. Der TrapHandler kann anhängig von genutzten GC
Algorithmus verschieden reagieren.

Die Segmentierung erfolt durch Maskierung des Registers GC_Config in welchem die
Segment größen festgelegt werden, die Bestimmung zu welchem Segment ein Zeiger oder
Objekt gehört durch abgleich des Zeigers/Objekts mit dem Register

Benchmark
Die Abbildung zeigt picoJava im Vergleich mit einem 80486- und einem Pentium-Prozessor.
Es wurden javac, der Sun Java Compiler, und ein nicht näherbestimmter Raytracer jeweils
8
    gc_notify(type = 0x27)

                                           Seite 27/ 31
auf dem Pentium und dem 486er mit einem Interpreter und einem JIT-Compiler getestet. Wie
man sieht schneidet picoJava 15 bis 20 mal schneller als der 486 mit Interpreter bzw. 5 mal
schneller als der Pentium mit einem JIT Compiler ab.

Dies Testergebnis ist jedoch insofern fraglich, da javac und der nicht weiter spezifizierte
Raytracer vielleicht extra gewählt wurden, weil sie besonders gut auf picoJava verarbeitet
werden können.

Zusammenfassung
Java biete durch seine Objektorientierung und den Bytecode viele Vorteile. Beim Einsatz von
Java in eingebetteten Echtzeitsystemen zeigt sich jedoch, dass interpretierter Bytecode in
der Regel zu langsam ist. Diese Probleme sollen durch einen Java Prozessor gelöst
werden

Der vorgestellte, von Sun spezifizierte Prozessor-Kern picoJava wurde von mehreren
großen Firmen lizenziert, ein picoJava-Boom blieb jedoch aus. Keiner der Lizenznehmer
hat jemals picoJava-basierte Chips verkauft9.

Bereits zum Erscheinen der Spezifikation wurde der Ansatz kritisch beäugt. Es waren bereits
Spezial-Prozessoren für andere Sprachen wie LISP und Smalltalk entwickelt worden, und
man hatte gesehen, dass Software-Implementierungen auf RISC-Chips bessere
9
    deswegen gibt es keinen Abschnitt "Implementierungen"

                                                   Seite 28/ 31
Performance boten. Man zweifelte daran, dass Suns picoJava besser performte. Und
tatsächlich stellte sich später heraus, dass picoJava weder schnell noch billig noch sparsam
genug war, um im Markt für Mobiltelefone und PDAs mithalten zu können.

Stattdessen wurde ein etwas anderer Ansatz für Kleingeräte populär: Java-Beschleuniger.
Dabei handelt es sich um Bausteine, die ähnlich wie Koprozessoren zusätzlich zum
Hauptprozessor verwendet werden können. So lässt sich beispielsweise Nazomis bereits
erwähnter Java-Koprozessor in bestehende Designs einbinden und erleichtert so
Kleingeräte-Herstellern die Verwendung von Java unter Beibehaltung einer bereits
vorhandenen Architektur.

Einen anderen Weg ging die Firma ARM. ARM hat seinen Chips den Java-VM-Befehlssatz
schlicht als dritten Befehlssatz hinzugefügt. Ein einfaches Umschalten macht so aus dem
herkömmlichen ARM-Chip eine Java VM.

                                          Seite 29/ 31
Quellen

SUN MICROELECTRONICS picoJava Microprocessor Cores

http://www.sun.com/microelectronics/picoJava/

           TM
the Java        Virtual Machine Specification, Second Edition

http://java.sun.com/docs/books/vmspec/

Harlan McGhan:                     "picoJava: a direct Execution Engine for Java Bytecode"

http://www.ece.purdue.edu/~arch/seminar/s chedules/spring00-pdf/mcghan98.pdf

Inside the Java Virtual Machine

http://www.artima.com/insidejvm/ed2/
Sun Gambles on Java Chips

http://www.byte.com/art/9611/sec6/art2.htm#116st3d2

picoJava2 ProzessorCore Description

http://epicentertech.net/java/Resources/Embedded_Java/Micro%20&%20Pico%20Java/picoJ
ava-II.pdf

Suns picoJava: http://www.sun.com/microelectronics/picoJava/

ARM: http://www.arm.com/

Nazomi:

http://www.nazomi.com/

                                                                Seite 30/ 31
Sie können auch lesen