JAVA-Prozessoren

Werbung
Java Prozessoren
Referat
Labor Computertechnik
WS 2004
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)
Handles
22
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 JavaStandards 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 DatencacheKontroller. 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 InstruktionscacheEinheit, 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
Tipush
bipush
sipush
char
reference
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
i2l
i2f
i2d
l2T
l2i
l2f
l2d
f2T
f2i
f2l
f2d
d2T
d2i
d2l
d2f
i2T
i2b
i2s
Tcmp
lcmp
Tcmpl
fcmpl
dcmpl
Tcmpg
fcmpg
dcmpg
if_TcmpOP
if_icmpOP
Treturn
ireturn
if_acmpOP
lretrun
Seite 10/ 31
freturn
dreturn
areturn
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
Konstante auf Stack legen
Laden/Speichern lokaler Variabeln
Stackverwaltung
Arithmetik
Schiebe- und Logikoperatoren
Verzweigungen und Vergleiche
Ausnahmebehandlung
Arrayverwaltung
Methodenrücksprünge
Switch-Table Verzweigungen
Konvertierungen
Monitore
Änderungen von Objektfeldern
Methodenaufrufe
Sonstige Objektbehandlung
Gesamtzahl
Anteil (in %)
Gesamtzahl
Anzahl von Befehlen mit der Länge:
13
82
10
24
12
27
1
20
7
2
15
2
4
4
3
226
100
1 Byte
8
40
10
24
12
5
1
17
7
15
2
141
62
2 Bytes
2
41
1
1
45
20
3 Bytes
3
1
19
1
4
3
3
34
15
Mehr als 3 Bytes
2
1
2
1
6
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. JVM4
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
Diagnose
Lesen/Schreiben von Registern
Beliebiges Laden/Speichern
Unterstützung anderer
Programmiersprachen
System Software Unterstützung
Gesamtzahl
Anteil (in %)
Gesamtzahl Anzahl von Befehlen mit der Länge:
8
49
35
6
1 Byte
-
2 Bytes
8
49
26
5
3 Bytes
9
1
17
115
100
2
2
2
10
98
85
5
15
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 picoJavaDekodierlogik 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
iadd
Opcode
Funktion
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
opc. 0xAB
0..3 bytes padding
byte 4
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
0xC2
Erwerben der Kontrolle
monitorenter
ü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
Taktzyklus ausgeführt werden.
abgespeichert.
wieder
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 SpillMechanismus (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, Registerbasierte 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 & SweepAlgorithmus. 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/
the Java
TM
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
Herunterladen