Folien zur Java Plattform - Professur für Mikrorechner - Technische ...
Folien zur Java Plattform - Professur für Mikrorechner - Technische ...
Folien zur Java Plattform - Professur für Mikrorechner - Technische ...
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
Farbverlauf<br />
Eingebettete Systeme<br />
<strong>Java</strong> in eingebetteten<br />
Systemen<br />
◆ <strong>Java</strong><strong>Plattform</strong><br />
◆ ClassFiles<br />
Christian Hochberger<br />
<strong>Professur</strong> <strong>Mikrorechner</strong><br />
Fakultät Informatik<br />
<strong>Technische</strong> Universität Dresden
Die <strong>Java</strong> <strong>Plattform</strong><br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 2
Architektur der VM<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 3
Struktur des ClassFiles<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 4
Einträge im ConstantPool<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 5
Einträge im ConstantPool (2)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 6
Constant Pool – Beispiel<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 7
Fields und Methods<br />
•Field Attribute:<br />
ConstantValue<br />
Synthetic<br />
•Method Attribute:<br />
Code<br />
Exceptions<br />
Synthetic<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 8
Code Attribut<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 9
Descriptor<br />
Field Descriptor: Field Type<br />
Method Descriptor: ( Field Type * ) Return Type<br />
Field Type: Base Type | Object Type | Array Type<br />
Object Type: Lclassname;<br />
Array Type: [ Field Type<br />
Base Type: B|C|D|F|I|J|S|Z<br />
Return Type: Field Type | V<br />
Beispiel:<br />
(JI)V ⇒ void wait(long timeout, int nanos)<br />
(ZIJLjava/lang/String;)Z ⇒<br />
boolean dummy(boolean a,int b,long c, String d)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 10
Class Loader<br />
Aufgaben:<br />
Laden: Lokalisieren und Importieren der Binärdaten einer<br />
Klasse<br />
Linken:<br />
Verifikation: Überprüfen der Korrektheit<br />
Vorbereitung: Allokation von Speicher <strong>für</strong> statische<br />
Felder<br />
Resolution: Transformation von symbolischen in<br />
direkte Referenzen<br />
Initialisierung: Ausführung des Codes <strong>zur</strong> Initialisierung<br />
der statischen Felder<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 11
Class Verifier<br />
Formatüberprüfung des ClassFiles<br />
Überprüfung aller Constant Pool Einträge<br />
z.B. getstatic: Eintrag muss vom Typ<br />
CONSTANT_Fieldref sein<br />
Überprüfung symbolischer Referenzen<br />
(Superklassen, referenzierte Klassen)<br />
Typprüfungen (final, abstract, Methodeninferenz)<br />
Überprüfung von Sprungadressen<br />
Datenflussanalyse, um Typkorrektheit zu prüfen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 12
ResolutionTypen<br />
Auflösen symbolischer Referenzen und Ersetzen durch direkte<br />
Referenzen:<br />
Unterscheidung von early resolution und late resolution<br />
ClassResolution<br />
Laden der entsprechenden Klasse (und Superklassen)<br />
MethodResolution:<br />
Suchen einer Methode mit passendem Namen<br />
Typinferenz ⇒ Stringmatching der Descriptors<br />
Prüfen der Zugriffsrechte<br />
FieldResolution:<br />
Suchen eines Fields mit passendem Namen<br />
Typprüfung<br />
Prüfen der Zugriffsrechte<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 13
Interne Repräsentation von Klassen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 14
Datentypen der JVM<br />
Datentypen<br />
Numerische<br />
Typen<br />
Referenzen<br />
Fließkomma<br />
Integral<br />
Objekt<br />
Array<br />
float<br />
double<br />
byte<br />
char<br />
short<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 15<br />
int<br />
long
Objekt Referenzen (Handle)<br />
Zweistufiges Verfahren, Objektreferenz ⇒ Handle ⇒<br />
Instanz<br />
Zusätzlicher Speicherplatz erforderlich<br />
Kompaktieren des Speichers einfacher<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 16
Objekt Referenzen (Direkter Zeiger)<br />
Einstufiges Verfahren, Objektreferenz ⇒ Instanz<br />
Zugriff auf Objektdaten schneller<br />
Kompaktieren des Speichers sehr schwer<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 17
<strong>Java</strong> Frames<br />
Beim Aufruf jeder <strong>Java</strong>Methode wird ein StackFrame erzeugt:<br />
Lokale Variablen:<br />
WortArray fester Größe<br />
Die ersten N Einträge sind die Parameter der Methode<br />
Instanzmethoden erhalten Objektreferenz als ersten<br />
Parameter<br />
Operanden Stack:<br />
Dient <strong>zur</strong> Aufnahme der Zwischenergebnisse<br />
VM hat keine Register (außer PC)<br />
Frame Daten:<br />
Zeiger auf ausgeführte Methode<br />
Zeiger auf Constant Pool der Klasse<br />
Zeiger auf Exception Tabelle<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 18
Lokaler Stack<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 19
Globaler Stack<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 20
Bytecode Struktur<br />
Alle Befehle bestehen aus einem Byte<br />
Für jede Methode einer Klasse wird ein ByteArray<br />
mit allen Befehlen gespeichert<br />
Argumente (meistens 1 oder 2 Byte) folgen im<br />
Bytestrom<br />
Argumente sind<br />
Konstanten<br />
Indizes in den Konstantenpool<br />
Komplexe Datenstrukturen (lookupswitch)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 21
Bytecode Gruppen<br />
Stack Operationen<br />
Typkonversionen<br />
Logische und Arithmetische Operationen<br />
ObjektHandling<br />
Flusskontrolle<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 22
Bytecode:Stack Operationen<br />
Ablegen von Konstanten auf dem Stack (iconst_[-1..5],<br />
fconst_[0..2],lconst_[0,1], dconst_[0,1],<br />
aconst_null)<br />
Ablegen von Immediate Werten auf dem Stack (bipush byte1,<br />
sipush byte1, byte2)<br />
Ablegen von Konstanten aus dem Konstantenpool auf dem Stack<br />
(ldc ibyte1, ldc_w ibyte1,ibyte2, ldc2_w ibyte1,ibyte2)<br />
StackManipulationen (pop, pop2, dup, dup2, swap, dup_x1, ...)<br />
Laden und Speichern von lokalen Variablen ([i,f,l,d,a]load<br />
ibyte1, [i,f,l,d,a]load_[0..3], [i,f,l,d,a]store<br />
ibyte1, ...)<br />
wide Präfix macht aus 8Bit Index 16Bit Index<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 23
Bytecode: Beispiel<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 24
Bytecode: Typkonversionen<br />
Umwandlung verschiedener primitiver Datentypen<br />
ineinander:<br />
Quelle int: i2l, i2f, i2d, i2b, i2s, i2c<br />
i2b und i2s schneiden obere Bytes ab und führen<br />
SignExtension durch. i2c schneidet ab und füllt den<br />
oberen Teil mit Nullen<br />
Quelle long: l2i, l2f, l2d<br />
Quelle float: f2i, f2l, f2d<br />
Quelle double: d2i, d2l, d2f<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 25
Bytecode: Logische und<br />
Arithmetische Operationen<br />
int: 32 Bit Zweierkomplement,<br />
long: 64 Bit Zweierkomplement<br />
Floating Point: IEEE 754<br />
float: 1 Bit Vorzeichen, 8 Bit Exponent, 23 Bit Mantisse<br />
double: 1 Bit Vorzeichen, 11 Bit Exponent, 52 Bit<br />
Mantisse<br />
Binäre Operationen ([i,l,f,d][add,sub,mul,div,rem])<br />
Unäre Operationen ([i,l,f,d]neg, iinc ibyte1,const,<br />
wide iinc ibyte1,ibyte2,const1,const2)<br />
logische Operationen ([i,l][shl,shr,ushr,and,or,xor])<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 26
Bytecodes: ObjektHandling<br />
Erzeugen eines Objektes: new ibyte1,ibyte2<br />
Lesen/Schreiben von Objektfeldern: [get,put]field<br />
ibyte1,ibyte2<br />
Lesen/Schreiben von statischen Objektfeldern:<br />
[get,put]static ibyte1, ibyte2<br />
Sicheres Typecasting: checkcast ibyte1,ibyte2<br />
Überprüfen des Objekttyps: instanceof ibyte1,ibyte2<br />
Anlegen von Feldern: newarray atype, anewarray<br />
ibyte1,ibyte2, multianewarray ibyte1,ibyte2,dim<br />
Feststellen der aktuellen Arraygröße: arraylength<br />
Lesen/Schreiben von ArrayElementen:<br />
[b,c,s,i,l,f,d,a][aload,astore]<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 27
Bytecodes: Flusskontrolle<br />
Alle Sprungdistanzen in Zweierkomplementdarstellung, Addition<br />
des Offsets <strong>zur</strong> Adresse des Opcodes<br />
Bedingte Sprünge<br />
Bedingung vom Stack: if[eq,ne,lt,le,gt,ge]<br />
obyte1,obyte2<br />
Vergleich zweier Werte:<br />
if_icmp[eq,ne,lt,le,gt,ge] obyte1,obyte2<br />
Vergleiche von long, float und double: lcmp, [f,d]cmp[g,l]<br />
Vergleiche von Objektreferenzen: if[non]null,<br />
if_acmp[eq,ne]<br />
Unbedingter Sprung: goto obyte1,obyte2,<br />
goto_w obyte1,obyte2,obyte3,obyte4<br />
Tabellensprünge: tableswitch, lookupswitch<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 28
tableswitch<br />
Komplexe Datenstruktur nach dem Bytecode<br />
DefaultWert<br />
Erster Index in Tabelle, Letzter Index in Tabelle<br />
Tabelle mit Sprungdistanzen<br />
Konstante Ausführungszeit<br />
Padding<br />
Allignment der 32 Bit Werte<br />
Adr % 2 2 == 0<br />
Indextabelle<br />
Erlaubt direkten Zugriff durch CPU<br />
opc pad0 ... padn<br />
Default<br />
Min. Index<br />
Max. Index<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 29<br />
...
lookupswitch<br />
Komplexe Datenstruktur nach dem Bytecode<br />
DefaultWert<br />
Anzahl WertOffset Paare<br />
Tabelle mit Paaren (Wert, Offset)<br />
Ausführungszeit unbekannt!<br />
WertOffsetTabelle<br />
opc pad0 ... padn<br />
Default<br />
NPairs<br />
Value Offset<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 30<br />
...
Bytecode Ausführung (Beispiel)<br />
Beispiele auf http://www.artima.com/insidejvm/applets/<br />
public class demo extends Object {<br />
void jumpAround(int a,int b) {<br />
int i;<br />
}<br />
}<br />
for (i=0; i
Exceptions<br />
Können durch Fehler bei der Abarbeitung entstehen<br />
Arithmetische Fehler (Division durch 0)<br />
Nullpointer Referenzierung<br />
Fehler beim Laden von Klassen<br />
Fehler beim IO<br />
Können explizit durch Programm erzeugt werden:<br />
athrow: Objektreferenz auf dem Stack wird als<br />
Exception geworfen<br />
Objekt muss Ableitung von Throwable sein<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 32
Exceptions im ClassFile<br />
Start PC, End PC<br />
Bytecode Bereich (End PC1!), der durch diesen tryBlock<br />
abgedeckt wird<br />
Handler PC<br />
Bytecode Offset, an dem der entsprechende Handler<br />
(catchBlock) beginnt<br />
Exception Type<br />
Constant Pool Index, der die ExceptionKlasse beschreibt, die<br />
abgefangen wird<br />
Exception Type == 0 (illegaler Constant Pool Index)<br />
⇒ Implementierung der finally Klauseln<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 33
Exception Processing<br />
Vorgehensweise beim Auftreten einer Exception:<br />
Durchsuchen der aktuellen Exception Table<br />
Aktueller PC liegt in einem Bereich:<br />
Entspricht Exception Type der aktuellen Exception?<br />
Ja ⇒ Handler ausführen<br />
Nein ⇒ Superklasse der aktuellen Exception mit Exception<br />
Type vergleichen<br />
Schritt wiederholen, bis Throwable erreicht ist<br />
Keinen passenden Handler gefunden?<br />
Aktuellen Stack Frame löschen<br />
Im übergeordneten Stack Frame Suche wiederholen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 34
Method Invocation<br />
invokestatic ibyte1,ibyte2:<br />
Neuen Stack Frame erzeugen,<br />
Argumente als lokale Variablen auf neuen Stack legen,<br />
Klassenmethode gemäß Constant Pool Eintrag aufrufen<br />
Resolution kann feste Adresse der Methode eintragen<br />
invokevirtual ibyte1,ibyte2:<br />
Neuen Stack Frame erzeugen,<br />
Objektreferenz als Argument 0 ablegen,<br />
Argumente als lokale Variablen auf neuen Stack legen,<br />
Instanzmethode gemäß Objektreferenz aufrufen<br />
Resolution kann Index in Methodentabelle des Objekttyps<br />
eintragen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 35
Method Invocation (2)<br />
invokeinterface ibyte1,ibyte2,nargs,0: ähnlich wie<br />
invokevirtual, aber andere Optimierung durch Resolution<br />
nötig<br />
invokespecial ibyte1,ibyte2<br />
Mischung aus invokestatic und invokevirtual:<br />
Klassenmethode aufrufen, aber Objektreferenz übergeben<br />
(statische Bindung)<br />
Konstruktoren<br />
Ausführen von privaten Methoden in Superklassen<br />
Ausführen von überschriebenen Methoden aus<br />
Superklassen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 36
Method Invocation (3)<br />
Native Methoden: Bleiben dem VM Implementierer überlassen<br />
Beenden von Methoden:<br />
return: Ohne Rückgabewert <strong>zur</strong>ückkehren<br />
[i,l,f,d,a]return: Entsprechenden Wert vom Stack<br />
lesen und auf aufrufendem Stack ablegen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 37
MethodenTabellen<br />
public class A extends Object {<br />
private int P1 ();<br />
public void O1 ();<br />
public void O2 ();<br />
}<br />
public class B extends A {<br />
private int P1 ();<br />
public void O3 ();<br />
}<br />
public class C extends A {<br />
private int P1 ();<br />
private int P2 ();<br />
public void O4 ();<br />
}<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 38
Synchronisation<br />
Monitorbasierte Synchronisation durch Bytecodes:<br />
monitorenter: Referenz vom Stack nehmen und Objekt<br />
blockieren<br />
Objekt bereits von anderem Thread blockiert:<br />
Diesen Thread suspendieren<br />
Objekt von diesem Thread oder noch nicht blockiert:<br />
Zähler erhöhen<br />
monitorexit: Referenz vom Stack nehmen und Zähler<br />
erniedrigen<br />
Zähler > 0: Thread läuft normal weiter<br />
Zähler = 0: Prüfen, ob anderer Thread wartet, evtl. neu<br />
schedulen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 39
SynchronisationBeispiel<br />
public class Sync extends Object {<br />
public void a(Object b) {<br />
int c;<br />
synchronized (b) {<br />
c=1;<br />
}<br />
}<br />
}<br />
0 aload_1<br />
1 astore_3<br />
2 aload_3<br />
3 monitorenter<br />
4 iconst_1<br />
5 istore_2<br />
6 aload_3<br />
7 monitorexit<br />
8 return<br />
9 aload_3<br />
10 monitorexit<br />
11 athrow<br />
Exception table:<br />
from to target type<br />
4 6 9 any<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 40
synchronized Methoden<br />
Bei synchronized Methoden muss VM Monitor belegen<br />
und freigeben:<br />
Bei Instanzmethoden wird this benutzt<br />
Bei statischen Methoden wird ClassObjekt benutzt<br />
public class Sync2 extends Object {<br />
public synchronized void a(Object b) {<br />
int c;<br />
c=1;<br />
}<br />
}<br />
0 iconst_1<br />
1 istore_2<br />
2 return<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 41
Wait Sets und Object<br />
Keine Bytecodes <strong>für</strong> Methoden wait(), notify() und<br />
notifyAll():<br />
wait() trägt aktuellen Thread in Wait Set des Objektes ein<br />
notify() nimmt einen Thread aus Wait Set des Objektes<br />
heraus<br />
notifyAll() nimmt alle Threads aus dem Wait Set des<br />
Objektes heraus<br />
Implementierung des Wait Sets nicht vorgegeben:<br />
bei notify() muss nicht höchst priorisierter Thread<br />
gewählt werden<br />
bei notify() muss nicht ältester Thread gewählt werden<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 42
Thread Behandlung<br />
Keine Bytecodes <strong>für</strong> Erzeugen, Beenden oder Manipulieren von<br />
Threads:<br />
Eintrag in die ThreadVerwaltung der VM durch<br />
Konstruktor (muss dann native Methode sein)<br />
oder Methode start() (muss in jedem Fall nativ sein)<br />
Methoden <strong>zur</strong> Manipulation von Threads müssen nativ sein<br />
(sleep(), setPriority(), join(), interrupt(),<br />
yield())<br />
Scheduling im Ermessen des Implementierers:<br />
TimeSlicing ?<br />
Strikte Prioritätensteuerung ?<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 43
Spezielle Bytecodes<br />
impdep[1,2]: implementationsspezifische Verwendung<br />
darf nicht in ClassFiles auftauchen<br />
Kann z.B. benutzt werden, um Resolution nativer<br />
Methoden zu implementieren<br />
breakpoint: Soll <strong>für</strong> Debugger benutzt werden<br />
jsr obyte1, obyte2: Aufruf von Unterprogrammen,<br />
Rücksprungadresse wird auf dem Stack abgelegt<br />
ret index: Rückkehr vom Unterprogramm,<br />
Adresse kommt aus lokaler Variable<br />
Unterprogramm speichert Rücksprungadresse in<br />
lokaler Variable<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 44
Resolution<br />
Drei Fälle unterscheidbar<br />
ClassRef (new, instanceof, checkcast, ...)<br />
CPIndex wird ersetzt durch Index in Klassentabelle<br />
FieldRef ([get,put]static, [get,put]field)<br />
Field:<br />
➢ CPIndex wird ersetzt durch Offset im Objekt<br />
➢ Probleme, wenn Objekt mehr als 65536 Felder enthält<br />
Static:<br />
➢ CPIndex wird zu Index in StaticTabelle<br />
(je Klasse oder global)<br />
Method/InterfaceRef (invokeXXX)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 45
Invokevirtual<br />
CPIndex beschreibt MethodRef<br />
Klasseninformation muss aus Objekt<br />
bezogen werden!<br />
Problem: Wieviel Argumente liegen<br />
auf Stack?<br />
Eigentlich erst bekannt, wenn man<br />
die Methode kennt.<br />
Lösung: Resolution trägt zwei Werte hinter<br />
invokevirtual_quick ein:<br />
Index in Methodentabelle (Klasse kommt ja aus Objekt)<br />
Anzahl der Argument auf dem Stack<br />
Stack<br />
this<br />
arg1<br />
arg2<br />
argn<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 46<br />
unbekannt
Invokeinterface<br />
Index der InterfaceMethoden kann in jeder Klasse<br />
anders sein<br />
Lösung:<br />
Für jedes implementierte Interface wird eine<br />
Methodentabelle angelegt (in jeder Klasse)<br />
Methodentabelle enthält Methoden dieser Klasse<br />
Resolution trägt dann ein:<br />
➢ Auswahl der Tabelle<br />
➢ Index in Tabelle<br />
➢ Anzahl der Argumente auf dem Stack<br />
Nur unwesentlich langsamer als Invokevirtual<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 47
Farbverlauf<br />
Eingebettete Systeme<br />
<strong>Java</strong> in eingebetteten<br />
Systemen<br />
Implementierung der JVM<br />
◆ Varianten der BytecodeAusführung<br />
◆ Native Routinen<br />
◆ IOBehandlung<br />
◆ ThreadModelle<br />
Christian Hochberger<br />
<strong>Professur</strong> <strong>Mikrorechner</strong><br />
Fakultät Informatik<br />
<strong>Technische</strong> Universität Dresden
Ausführung des Bytecodes<br />
Interpretation<br />
Compilation<br />
AheadofTime Compilation<br />
JustinTime Compilation<br />
HostspotCompilation<br />
Hybride Ansätze<br />
Alternativer Zwischencode<br />
Hardware Implementierung<br />
Mikroprogrammierte Varianten<br />
HardwareJIT<br />
BefehlssatzErweiterungen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 49
Interpretation<br />
Analyse der auszuführenden Bytecodes <strong>zur</strong> Laufzeit<br />
Aufruf entsprechender Programmstücke <strong>für</strong> jeden<br />
Befehl<br />
Eigenschaften:<br />
Einfachste Implementierung<br />
Kleinste Implementierung<br />
Langsamste Implementierung<br />
➢ Immer wieder Analyse der Befehle<br />
➢ Stack wird auf Speicherstück abgebildet<br />
⇒ sehr viele Speicherzugriffe<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 50
InterpretationGrundstruktur<br />
Endlosschleife:<br />
Lesen des Bytecodes<br />
(dabei Weiterschalten des PC)<br />
Mehrfachverzweigung über Befehl<br />
evtl. Einlesen der Parameter<br />
(dabei Weiterschalten des PC)<br />
Ausführung des Befehls<br />
Verlassen der Schleife bei<br />
Ende der Methode ([x]return)<br />
Unterbrechung durch andere Threads<br />
blockierenden Operationen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 51
Intepretation Wichtige Daten<br />
Zeiger auf Code (PC)<br />
Zeiger auf Top of Stack<br />
Zeiger auf Beginn der lokalen Variablen<br />
(Zeiger auf aktuellen Frame)<br />
Für Zugriffe auf ExceptionTabelle<br />
Für Methodenaufrufe<br />
(Zeiger auf aktuellen Thread)<br />
Bei Unterbrechung durch andere Threads oder<br />
blockierenden Operationen<br />
Abbildung möglichst auf Prozessorregister<br />
(daher typischerweise in lokalen Variablen)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 52
Interpretation Verbessert<br />
Benutzung des "Computed Goto":<br />
Tabelle mit Sprungmarken <strong>für</strong> jeden Bytecode<br />
Am Ende der Interpretation jedes Befehls:<br />
➢ Laden des nächsten Befehls<br />
➢ direkter Sprung zum nächsten Programmstück<br />
Vorteil:<br />
➢ Vermeidung der Schleife<br />
➢ (Vermeidung der Bereichsprüfung bei switch<br />
Anweisung)<br />
Nachteile:<br />
➢ Kein ANSIC !!!<br />
➢ Größerer Speicherplatzbedarf<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 53
Compilation<br />
Aufgaben:<br />
Abbildung des Bytecodes auf native<br />
Prozessorinstruktionen<br />
Abbildung der Stackmaschine auf eine<br />
Registermaschine (meistens)<br />
Probleme:<br />
Abbildung hochgradig prozessorspezifisch<br />
Anzahl der Register<br />
Erhalt der Echtzeitfähigkeit<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 54
Compilation Stacktiefe<br />
Verteilung der Stacktiefen im Kertasarie API<br />
100<br />
90<br />
80<br />
70<br />
60<br />
50<br />
40<br />
30<br />
20<br />
10<br />
0<br />
0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22<br />
Summierte Häufigkeit<br />
in %<br />
Häufigkeit in %<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 55
AheadOfTime Compilation<br />
Zwei Varianten:<br />
<strong>Java</strong> ⇒ Nativer Code<br />
Bytecode ⇒ Nativer Code<br />
Vorteile:<br />
Beliebig viel Zeit <strong>für</strong> Optimierung<br />
Kein Compiler im System erforderlich<br />
Nachteile:<br />
Hoher Aufwand <strong>für</strong> Typintrospektion<br />
Hoher Speicherplatzverbrauch<br />
Kein dynamisches Nachladen von Klassen<br />
Lösungen:<br />
➢ Classloader mit Compiler<br />
➢ Zusätzlicher Interpreter <strong>für</strong> nachgeladene Klassen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 56
JustInTime Compilation<br />
Compilation der Methoden, wenn sie gebraucht<br />
werden (JustInTime)<br />
Vorteile:<br />
Nur benötigte Methoden werden compiliert<br />
Nachteile:<br />
Compiler muss im System sein<br />
Hoher Portierungsaufwand<br />
Hohe StartupVerzögerung<br />
Hoher Speicherplatzverbrauch (Klassen + Compiler)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 57
Hotspot Compilation<br />
Compilation von Methodenfragmenten bei<br />
mehrfacher Nutzung<br />
Vorteile:<br />
Extrem hohe Optimierung möglich<br />
(da Codefragmente kurz)<br />
Geringerer Speicherbedarf (Klassen) als bei JIT<br />
Nicht so hohe StartupVerzögerung<br />
Nachteile:<br />
Sehr viel Speicherplatz <strong>für</strong> Compiler<br />
Komplizierte VM Konstruktion<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 58
Registermaschine<br />
Hauptursache langsamer Interpretation:<br />
Häufige Speicherzugriffe<br />
Genauere Analyse:<br />
➢ CodeZugriffe landen im Cache<br />
➢ StackZugriffe passen nicht in Cache<br />
Idee: Abbildung des Stack auf Register<br />
Gewinn:<br />
Speicherzugriffe auf Stack werden vermieden<br />
Ca. 30% weniger Instruktionen (StackHandling)<br />
Problem: Nur machbar, wenn genügend Register<br />
vorhanden<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 59
Hybride Ansätze<br />
Implementation zweier Interpreter in einer JVM<br />
RegisterCode Interpreter<br />
Normaler BytecodeInterpreter <strong>für</strong><br />
➢ wenig benutzten Code<br />
➢ Code der nicht transformiert werden kann<br />
(Registerbeschränkungen)<br />
Übersetzung des Bytecodes bei Erreichen von<br />
Schwellwerten<br />
z.B. Methode wird zum nten mal ausgeführt<br />
Wechsel zwischen den Interpretern bei<br />
Methodenaufrufen oder Returns<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 60
Hardware Implementierungen der<br />
JVM<br />
Direkte Bytecode Prozessoren<br />
Bytecode als nativer Befehlssatz<br />
Zusätzliche Befehle <strong>für</strong> HardwareZugriffe + Garbage<br />
Collection<br />
CodeMorphing Prozessoren<br />
OntheFly Transformation des Bytecode in nativen<br />
Code des Zielprozessors<br />
Befehlssatzerweiterungen<br />
Prozessor versteht Bytecode und anderen Befehlssatz<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 61
Direkte Bytecode Ausführung<br />
Interpretation der Bytecodes durch Mikroprogramm<br />
Probleme:<br />
Effiziente StackAbbildung<br />
➢ Stack meist im internen Speicher (Geschwindigkeit,<br />
Parallelität)<br />
➢ Besondere Behandlung bei Speicherüber/unterlauf<br />
Kein Pipelining<br />
Beispiele:<br />
➢ Befehle haben unregelmäßige Struktur<br />
➢ Komplexität der Operationen stark schwankend<br />
Pico<strong>Java</strong> II, Ajile aj100, JOP<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 62
<strong>Java</strong> Optimized Prozessor<br />
Sehr einfacher BytecodeProzessor<br />
4 stufige Pipeline<br />
Abbildung des Bytecode auf Microcode<br />
Einfache Befehle: 1 Microcode<br />
Komplexe Befehle: Mehrere Microcode Befehle<br />
Aber: Viele komplexe Befehle werden in <strong>Java</strong><br />
programmiert<br />
(benutzen dann nur die Bytecodes, die direkt auf<br />
Microcode abgebildet werden können)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 63
JOP Architektur<br />
Bytecode<br />
Fetch, translate<br />
and branch<br />
Microcode<br />
Fetch and<br />
branch<br />
Microcode<br />
Decode<br />
bytecode branch condition<br />
next bytecode microcode branch condition<br />
bytecode branch<br />
branch<br />
Stack<br />
Address<br />
generation<br />
Microcode<br />
Execute<br />
Stack<br />
RAM<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 64
Code Morphing<br />
Quasi JIT in Hardware<br />
Ähnlich wie z.B. Transmeta Crusoe<br />
Vorteile:<br />
Keine Zwischenspeicherung des Compilats<br />
Einfache Einbindung nativen Codes (z.B.:<br />
Betriebssytem)<br />
Probleme:<br />
Direkte Abbildung von Stackpositionen auf Register<br />
Beschränkt durch Anzahl verfügbarer Register<br />
Beispiel:<br />
JStar von Nazomi (<strong>für</strong> ARM Prozessoren)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 65
Befehlssatzerweiterungen<br />
Prozessor versteht mehr als einen Befehlssatz<br />
Umschalten des Betriebsmodus, um Bytecode<br />
auszuführen<br />
Nicht implementierte Bytecodes führen zu<br />
Exceptions ⇒ Behandlung in Software<br />
Beispiel:<br />
Jazelle <strong>für</strong> verschiedene ARMArchitekturen<br />
Problem:<br />
➢ Nur Methoden mit max. 4 Stackpositionen können<br />
ausgeführt werden<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 66
Thread Modelle<br />
Implementierung von <strong>Java</strong>Threads<br />
Green Threads:<br />
Die gesamte VM läuft als ein OSThread/Prozess<br />
Native Threads:<br />
Jeder <strong>Java</strong> Thread läuft als ein OSThread<br />
Wahl des ThreadModells hat wesentlichen Einfluss<br />
auf:<br />
Code Umfang<br />
Portierbarkeit<br />
Echtzeitfähigkeit<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 67
Green Threads<br />
Vorteile:<br />
Einfache Portierbarkeit<br />
(Zielsystem muss keine Threads beherrschen)<br />
Weniger Critical Sections<br />
Nachteile:<br />
➢ Geringerer Code Umfang<br />
Keine blockierenden Operationen in Threads erlaubt<br />
➢ Ummantelung aller Betriebssystemaufrufe nötig<br />
Benutzung von compiliertem Code<br />
➢ Verlust der Echtzeitfähigkeit<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 68
Native Threads<br />
Vorteile:<br />
Einfacherer Aufbau der Interpretationsschleife<br />
(Keine Abfrage der Signalvariable nötig)<br />
Besseres Laufzeitverhalten<br />
Nachteile:<br />
Viele Mutexe nötig<br />
➢ Bei Synchronisation auf ein Objekt<br />
➢ Bei Garbage Collection<br />
Hoher Portierungsaufwand<br />
➢ OSspezifische Routinen <strong>für</strong> wait() und notify()<br />
Schlechtere Laufzeit bei ThreadErzeugung<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 69
Native Routinen<br />
Werden benötigt <strong>für</strong><br />
Den Zugriff auf Hardware<br />
Den Zugriff auf das Betriebssystem<br />
Für die Implementierung zeitkritischer Aufgaben<br />
(wenn z.B. kein JIT oder HotspotCompiler verfügbar)<br />
Implementierung des GarbageCollectors<br />
ThreadHandling<br />
Reflection + Serialisierung<br />
Klassische Realisierung:<br />
<strong>Java</strong> Native Interface (JNI)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 70
Native Routinen in Hardware<br />
Implementierungen<br />
CodeMorphing + Befehlssatzerweiterungen:<br />
Kein Problem, nativer Code verfügbar<br />
Direkte BytecodeAusführung<br />
Kein nativer Code verfügbar<br />
Lösung: Einführung neuer Bytecodes<br />
Peek<br />
➢ Liest Adresse vom Stack<br />
➢ Legt MEM(Adresse) auf den Stack<br />
Poke<br />
➢ Liest Adresse und Wert vom Stack<br />
➢ Schreibt Wert an MEM(Adresse)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 71
Native Routinen in Hardware<br />
Implementierungen (2)<br />
Durch Peek + Poke<br />
Implementierung des GC<br />
(entsetzlich langsam, z.B. ajile aj100)<br />
Implementierung des HardwareZugriffs<br />
Implementierung des ThreadHandlings<br />
Evtl. zusätzliche Bytecodes <strong>für</strong><br />
ThreadHandling<br />
Peek+Poke <strong>für</strong> kleinere Datentypen (Bit, Byte)<br />
OS muss in <strong>Java</strong> impementiert sein<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 72
Native Routinen Probleme<br />
Objekterzeugung:<br />
Nativer Code erzeugt neue Objekte<br />
Problemstellen:<br />
➢ Kein Speicher mehr frei ⇒ Garbage Collector läuft<br />
➢ Vorher erzeugte Objekte sind nicht referenzierbar<br />
(werden ja nur vom nativen Code referenziert)<br />
➢ Vorher erzeugte Objekte werden fälschlich freigegeben<br />
Lang laufende oder blockierende Routinen<br />
Bei Green Threads nicht erlaubt<br />
Programmierer muss sinnvoll programmieren<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 73
JNI<br />
Standardisierte Schnittstelle <strong>für</strong> die Implementierung<br />
von nativen Routinen<br />
Native Routinen werden dynamisch<br />
nachgeladen(DLL, shared Library, ...)<br />
Bestandteil des Standards<br />
Problem: OS kann nicht dynamisch nachladen<br />
⇒ kein JNI nutzbar<br />
VM kann abfragen, welche Methoden in DLL<br />
implementiert sind<br />
Standard JDK: Statische Initialisierung von Object<br />
lädt DLL mit den nativen Routinen <strong>für</strong> API (java.lang)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 74
JNI (2)<br />
JNI bietet:<br />
Zugriff auf die Argumente der implementierten<br />
Methode<br />
Native Methoden zum Zugriff auf ObjektFelder<br />
➢ Auswahl durch symbolische Information<br />
➢ Resolution der Namen erforderlich<br />
Möglichkeit Ergebnisse <strong>zur</strong>ückzugeben<br />
Möglichkeit Exceptions zu werfen<br />
Möglichkeit Objekte zu erzeugen<br />
Möglichkeit (<strong>Java</strong>)Methoden von Objekten auf<strong>zur</strong>ufen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 75
JNI – Probleme in ES<br />
CodeUmfang <strong>für</strong> JN I: ca. 500KB<br />
Ursache:<br />
Behandlung aller Spezialfälle<br />
➢ Nativer Code ruft <strong>Java</strong> Methode auf<br />
➢ Zugriff auf statische Klassenfelder<br />
➢ ...<br />
Dynamisches Nachladen<br />
Zugriffs und Hilfsfunktionen<br />
Alternative:<br />
KNI (KVM Native Interface)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 76
KNI<br />
Eincompilierte Tabelle aller nativen Methoden<br />
Vorteil:<br />
Immer implementierbar (sehr portabel)<br />
Effizienterer Übergang zw. <strong>Java</strong> und nativer Ebene<br />
Nachteile:<br />
Neue native Methoden: VM muss neu compiliert<br />
werden<br />
Tabelle kann sehr groß werden<br />
Kein Aufruf von <strong>Java</strong> Methoden aus nativem Code<br />
heraus möglich<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 77
KNI Eigenschaften<br />
Resolution nativer Routinen:<br />
Suche nach nativen Routinen beim Klassenladen<br />
CodeZeiger in MethodenStruktur zeigt auf Adresse<br />
des nativen Codes<br />
Alle nativen Routinen haben gleiche Signatur<br />
Zugriff auf Stack<br />
➢ Lesen der Argumente<br />
➢ Ablegen des Ergebnisses<br />
Rückgabewert kann Exception spezifizieren<br />
Besondere Behandlung blockierender Routinen<br />
erforderlich<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 78
KNI Probleme<br />
VMspezifische Techniken <strong>für</strong><br />
Zugriff auf Argumente<br />
Zugriff auf Objektfelder<br />
Objekterzeugung (mit GCProblematik)<br />
Keine Unterstützung <strong>für</strong> Aufruf von <strong>Java</strong>Methoden<br />
aus nativem Code heraus<br />
Wird in der Praxis aber auch selten gebraucht<br />
Sehr viel Disziplin nötig<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 79
Ein/Ausgabe<br />
Zwei wesentliche Bereiche:<br />
DateiIO<br />
SocketIO<br />
Wesentliches Problem:<br />
IOAufrufe können blockieren<br />
Bei Green Threads nicht erlaubt<br />
Lösung je nach Betriebssystem:<br />
Asynchrones IO<br />
IOThreads <strong>für</strong> jeden Socket<br />
Separate IOThreads<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 80
SocketIO<br />
Problematische Aufrufe:<br />
Connect<br />
Aktiver Verbingungsaufbau<br />
Write<br />
Kann hängen, wenn interne Puffer noch gefüllt<br />
Read<br />
Accept<br />
ServerSocket: Externe Verbindung kann zu<br />
beliebigem Zeitpunkt hergestellt werden<br />
(Close)<br />
Evtl. Noch warten, bis SchreibPuffer geleert sind<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 81
Asynchrones IO<br />
Socket wird auf NonBlocking gestellt<br />
Aufrufe, die blockieren würden<br />
Kehren sofort <strong>zur</strong>ück<br />
Liefern speziellen Fehlercode (EWOULDBLOCK)<br />
Zusätzlich wird asynchrone Benachrichtigung <strong>für</strong><br />
Socket aktiviert:<br />
Wenn gewünschter IOAufruf möglich ist, wird ein<br />
Signal ausgelöst<br />
SignalBehandlung läuft asynchron zum Programm<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 82
Asynchrones IO (2)<br />
Implementierung:<br />
Native Routine versucht den gewünschten Aufruf<br />
durchzuführen<br />
Ergebnis: EWOULDBLOCK<br />
Native Routine kehrt <strong>zur</strong>ück<br />
Spezieller Rückgabewert an den Interpreter<br />
Interpreter stellt PC wieder auf Anfang des nativen<br />
Aufrufs<br />
Thread wird als wartend markiert<br />
Erneute Aktivierung des Threads:<br />
Gleicher nativer Aufruf wird noch einmal durchgeführt<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 83
Asynchrones IO (3)<br />
SignalHandler:<br />
Bei eintreffendem Signal nicht klar, welcher Thread<br />
weiterarbeiten kann<br />
SelectAufruf prüft, <strong>für</strong> welchen Socket welche<br />
Operationen möglich sind<br />
Interne Tabelle liefert Informationen, welcher Thread<br />
auf welchen SocketZustand wartet<br />
Tabelle wird durch native Aufruf aufgebaut<br />
Betroffene <strong>Java</strong>Threads wieder als lauffähig<br />
markieren<br />
Mutex zw. VM und SignalHandler erforderlich<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 84
IOThreads <strong>für</strong> jeden Socket<br />
VM erzeugt 2 OSThreads <strong>für</strong> jeden Socket:<br />
1 zum Lesen (und <strong>für</strong> Accept)<br />
1 zum Schreiben (und <strong>für</strong> Connect)<br />
Nativer Aufruf stellt AufrufDaten in interne Struktur<br />
Nativer Aufruf signalisiert betroffenem Thread<br />
Arbeitsauftrag (z.B.: Semaphor, SystemEvent)<br />
Nativer Aufruf wird beendet (PC <strong>zur</strong>ückstellen)<br />
IOThread erledigt Auftrag (mit synchronem IO)<br />
IOThread markiert betroffenen Thread als lauffähig<br />
Nativer Aufruf wird wiederholt (Daten aus interner<br />
Struktur)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 85
Separate IOThreads<br />
Ein zusätzlicher IOThread:<br />
Wartet in Select auf Beendung möglicher IOAufrufe<br />
Wenn gewünschter Aufruf möglich, betroffenen <strong>Java</strong><br />
Thread als lauffähig markieren<br />
Problem:<br />
IOThread steht im Select und ein neuer Auftrag soll<br />
Lösung:<br />
angenommen werden<br />
Zusätzlicher Socket, der VM mit sich selbst verbindet<br />
Select wartet immer auch auf diesen Socket<br />
Unterbrechung durch Senden von Daten an sich selbst<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 86
Garbage Collection<br />
Prinzipielles Problem:<br />
Auffinden nicht referenzierter Objekte<br />
Freigeben des Speicherplatzes dieser Objekte<br />
Welche Objekte werden referenziert ?<br />
Definition von WurzelReferenzen (StackFrames, Lokale<br />
Variablen, statische KlassenFelder, ...)<br />
Alle Objekte die direkt durch die Wurzeln referenziert<br />
werden (Objekte sind lebendig)<br />
Alle Objekte die von lebendigen Objekten referenziert<br />
werden<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 87
GC: Konservativ vs. Vollständig<br />
Welche Einträge des Stacks sind Referenzen?<br />
VM kann Referenzen von anderen Typen unterscheiden:<br />
Menge aller lebendigen Objekte kann exakt bestimmt<br />
werden<br />
Vollständige GC möglich<br />
VM kann Referenzen nicht von anderen Typen<br />
unterscheiden:<br />
Elemente des Stacks können versehentlich als<br />
Objektreferenz interpretiert werden<br />
Menge der lebendigen Objekte kann nicht exakt<br />
festgestellt werden<br />
Konservative GC<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 88
GC: Strategien<br />
Reference Counting<br />
zusätzlichen Zähler in Objekt aufnehmen (Zähler=0<br />
⇒ Objekt nicht referenziert)<br />
astore Bytecode:<br />
• Zähler des Objektes von überschriebener Referenz<br />
erniedrigen<br />
• Zähler des Objektes von neuer Referenz erhöhen<br />
Beim Löschen eines Frames Zähler aller Objekte<br />
erniedrigen<br />
⇒ sehr hoher Aufwand<br />
Tracing Garbage Collection<br />
Mark and Sweep<br />
Copying Collection<br />
Generational Collection<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 89
Mark and Sweep<br />
Zweiphasiger Algorithmus:<br />
Phase 1 (Mark)<br />
Markierungen aller Objekte entfernen<br />
Von den Wurzeln aus alle Objekte markieren<br />
Von den markierten Objekten aus alle<br />
Referenzen verfolgen und Objekte markieren<br />
letzten Schritt wiederholen, bis alle<br />
Referenzen auf markierte Objekte zeigen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 90
Mark and Sweep (2)<br />
Phase 2 (Sweep)<br />
Heap sequentiell durchsuchen<br />
Alle nicht markierten Objekte freigeben<br />
Probleme:<br />
Nicht unterbrechbar<br />
(Kann modifiziert werden)<br />
Fragmentierung des Heap ( ⇒ Kompaktieren)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 91
Copying Collection<br />
Aufteilung des Speichers in zwei Bereiche<br />
Während des Verfolgens von Referenzen werden<br />
referenzierte Objekte in anderen Speicherbereich<br />
kopiert<br />
ForwardReferenzen werden an alten Platz gestellt<br />
Weitere Referenzen auf altes Objekt werden durch<br />
ForwardReferenz ersetzt<br />
Nach Beendigung: Alter Bereich leer, neuer Bereich<br />
kompakt<br />
Neue Objekte werden aus neuem Bereich allokiert<br />
Neuer Bereich voll ⇒ GC erneut starten<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 92
Generational Collection<br />
Lebensdauer vieler Objekte sehr unterschiedlich:<br />
Sehr viele, (meist) kleine kurzlebige Objekte<br />
Wenige, (meist) große langlebige Objekte<br />
Konsequenz:<br />
Aufteilung des Heap in Generationen<br />
Jüngste Generation wird am häufigsten »collected«<br />
Älteste Generation wird selten »collected«<br />
Lebendige Objekte werden in die nächst ältere<br />
Generation kopiert<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 93
EchtzeitProblematik<br />
Vorgestellte Verfahren sind nicht unterbrechbar<br />
Eintreffende Ereignisse werden erst bearbeitet, wenn<br />
GC beendet ⇒ inakzeptable Verzögerungen in<br />
EchtzeitSystemen<br />
Zwei mögliche Lösungen:<br />
1. Unterbrechbare GCVerfahren<br />
2. Inkrementelle GCVerfahren, mit kurzen<br />
GCPausen (z.B. TrainAlgorithmus, in <strong>Java</strong> SDK 1.3<br />
implementiert)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 94
Unterbrechbare GCVerfahren<br />
Problem:<br />
Halbfertiger Erreichbarkeitsgraph kann durch<br />
<strong>Java</strong>Programm verändert werden<br />
Veränderungen durch Programm müssen im<br />
Graphen mitgeführt werden<br />
Lösung:<br />
TriColoring<br />
➢ Zuordnung von Farben zu Objekten<br />
➢ Beschreibt Zustand des<br />
Erreichbarkeitsgraphen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 95
TriColoring<br />
Vor Traversierung Während Traversierung<br />
Nach Traversierung<br />
Nicht erreichtes Objekt<br />
Gerade betrachtetes Objekt<br />
Erreichtes Objekt<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 96
Starke + Schwache Invariante<br />
Zwei mögliche Graphstrukturen:<br />
Schwache Invariante:<br />
Mindestens ein Weg zw. schwarzen und weißen<br />
Objekten geht über ein graues Objekt<br />
Snapshot at the Beginning<br />
Starke Invariante:<br />
Alle Wege zw. schwarzen und weißen Objekten gehen<br />
über graue Objekte<br />
Incremental Update<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 97
Barrieren<br />
Verhindern Verletzung der Invarianten<br />
Lese und Schreibbarrieren möglich<br />
LeseBarriere:<br />
Bei Zugriff auf weißes Objekt wird dieses grau gefärbt<br />
Verletzt weder starke noch schwache Invariante<br />
SchreibBarriere:<br />
Unterscheidung <strong>für</strong> starke und schwache Invariante<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 98
Schreibbarriere <strong>für</strong> die starke<br />
Invariante<br />
Problematisch: Veränderung an schwarzen Objekten<br />
Wird eine Referenz auf ein weißes Objekt in ein<br />
schwarzes geschrieben, dann wird das weiße Objekt<br />
grau gefärbt<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 99
Schreibbarriere <strong>für</strong> die schwache<br />
Invariante<br />
Nicht neues Objekt wird betrachtet, sondern das alte<br />
Altes Objekt weiß: Dann grau färben.<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 100
Referenzen<br />
Werden in <strong>Java</strong> durch Ableitungen der abstrakten<br />
Klasse Reference erzeugt<br />
Drei Unterarten verfügbar:<br />
SoftReference: Bleibt so lange wie möglich erhalten<br />
(Entfernen bei Speichermangel)<br />
WeakReference: Bleibt erhalten, solange noch<br />
Speicher da ist (Entfernen bei jedem GCLauf)<br />
PhantomReference: Bleibt nicht erhalten<br />
(Entfernen wann immer es der JVM gefällt)<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 101
Referenzen – API<br />
Reference(Object o) oder<br />
Reference(Object o, ReferenceQueue rq)<br />
clear() setzt die ObjektReferenz auf null<br />
get() liefert die ObjektReferenz (oder evtl. null,<br />
wenn das Objekt freigegeben wurde)<br />
enqueue() Einreihen in die Warteschlange<br />
isEnqueued() bereits eingereiht?<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 102
ReferenzWarteschlangen<br />
Verwalten ReferenceObjekte, die freigegeben wurden<br />
Müssen beim Erzeugen des ReferenceObjektes<br />
angegeben werden<br />
Methoden:<br />
poll(): Prüft ob Queue eine Referenz enthält<br />
remove(): Entfernt erstes Element der Queue<br />
(blockiert, wenn keine Referenz vorhanden)<br />
remove(long timeout): Wie remove(), aber mit<br />
Timeout<br />
enqueue(Reference r): Einreihen einer Referenz.<br />
Wird in der Regel vom GC aufgerufen<br />
Chr. Hochberger, Fakultät Informatik, TU Dresden 103