28.04.2013 Aufrufe

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 ...

MEHR ANZEIGEN
WENIGER ANZEIGEN

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 />

◆ Class­Files<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 Class­Files<br />

Chr. Hochberger, Fakultät Informatik, TU Dresden 4


Einträge im Constant­Pool<br />

Chr. Hochberger, Fakultät Informatik, TU Dresden 5


Einträge im Constant­Pool (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 Class­Files<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


Resolution­Typen<br />

Auflösen symbolischer Referenzen und Ersetzen durch direkte<br />

Referenzen:<br />

Unterscheidung von early resolution und late resolution<br />

Class­Resolution<br />

Laden der entsprechenden Klasse (und Superklassen)<br />

Method­Resolution:<br />

Suchen einer Methode mit passendem Namen<br />

Typinferenz ⇒ Stringmatching der Descriptors<br />

Prüfen der Zugriffsrechte<br />

Field­Resolution:<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 Stack­Frame erzeugt:<br />

Lokale Variablen:<br />

Wort­Array 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 Byte­Array<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 />

Objekt­Handling<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 />

Stack­Manipulationen (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 8­Bit Index 16­Bit 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 />

Sign­Extension 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: Objekt­Handling<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 Array­Elementen:<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 />

Default­Wert<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 />

Default­Wert<br />

Anzahl Wert­Offset Paare<br />

Tabelle mit Paaren (Wert, Offset)<br />

Ausführungszeit unbekannt!<br />

Wert­Offset­Tabelle<br />

opc pad0 ... padn<br />

Default<br />

N­Pairs<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 Class­File<br />

Start PC, End PC<br />

Bytecode Bereich (End PC­1!), der durch diesen try­Block<br />

abgedeckt wird<br />

Handler PC<br />

Bytecode Offset, an dem der entsprechende Handler<br />

(catch­Block) beginnt<br />

Exception Type<br />

Constant Pool Index, der die Exception­Klasse 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


Methoden­Tabellen<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


Synchronisation­Beispiel<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 Class­Objekt 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 Thread­Verwaltung 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 />

Time­Slicing ?<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 Class­Files 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 />

CP­Index wird ersetzt durch Index in Klassentabelle<br />

FieldRef ([get,put]static, [get,put]field)<br />

Field:<br />

➢ CP­Index wird ersetzt durch Offset im Objekt<br />

➢ Probleme, wenn Objekt mehr als 65536 Felder enthält<br />

Static:<br />

➢ CP­Index wird zu Index in Static­Tabelle<br />

(je Klasse oder global)<br />

Method/Interface­Ref (invokeXXX)<br />

Chr. Hochberger, Fakultät Informatik, TU Dresden 45


Invokevirtual<br />

CP­Index 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 Interface­Methoden 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 Bytecode­Ausführung<br />

◆ Native Routinen<br />

◆ IO­Behandlung<br />

◆ Thread­Modelle<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 />

Ahead­of­Time Compilation<br />

Just­in­Time Compilation<br />

Hostspot­Compilation<br />

Hybride Ansätze<br />

Alternativer Zwischencode<br />

Hardware Implementierung<br />

Mikroprogrammierte Varianten<br />

Hardware­JIT<br />

Befehlssatz­Erweiterungen<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


Interpretation­Grundstruktur<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 Exception­Tabelle<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 ANSI­C !!!<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


Ahead­Of­Time 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


Just­In­Time Compilation<br />

Compilation der Methoden, wenn sie gebraucht<br />

werden (Just­In­Time)<br />

Vorteile:<br />

Nur benötigte Methoden werden compiliert<br />

Nachteile:<br />

Compiler muss im System sein<br />

Hoher Portierungsaufwand<br />

Hohe Startup­Verzö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 Startup­Verzö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 />

➢ Code­Zugriffe landen im Cache<br />

➢ Stack­Zugriffe passen nicht in Cache<br />

Idee: Abbildung des Stack auf Register<br />

Gewinn:<br />

Speicherzugriffe auf Stack werden vermieden<br />

Ca. 30% weniger Instruktionen (Stack­Handling)<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 />

Register­Code Interpreter<br />

Normaler Bytecode­Interpreter <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 n­ten 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> Hardware­Zugriffe + Garbage­<br />

Collection<br />

Code­Morphing Prozessoren<br />

On­the­Fly 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 Stack­Abbildung<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 Bytecode­Prozessor<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 ARM­Architekturen<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 OS­Thread/Prozess<br />

Native Threads:<br />

Jeder <strong>Java</strong> Thread läuft als ein OS­Thread<br />

Wahl des Thread­Modells 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 />

➢ OS­spezifische Routinen <strong>für</strong> wait() und notify()<br />

Schlechtere Laufzeit bei Thread­Erzeugung<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 Hotspot­Compiler verfügbar)<br />

Implementierung des Garbage­Collectors<br />

Thread­Handling<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 />

Code­Morphing + Befehlssatzerweiterungen:<br />

Kein Problem, nativer Code verfügbar<br />

Direkte Bytecode­Ausfü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 Hardware­Zugriffs<br />

Implementierung des Thread­Handlings<br />

Evtl. zusätzliche Bytecodes <strong>für</strong><br />

Thread­Handling<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 Objekt­Felder<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 />

Code­Umfang <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 />

Code­Zeiger in Methoden­Struktur 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 />

VM­spezifische Techniken <strong>für</strong><br />

Zugriff auf Argumente<br />

Zugriff auf Objektfelder<br />

Objekterzeugung (mit GC­Problematik)<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 />

Datei­IO<br />

Socket­IO<br />

Wesentliches Problem:<br />

IO­Aufrufe können blockieren<br />

Bei Green Threads nicht erlaubt<br />

Lösung je nach Betriebssystem:<br />

Asynchrones IO<br />

IO­Threads <strong>für</strong> jeden Socket<br />

Separate IO­Threads<br />

Chr. Hochberger, Fakultät Informatik, TU Dresden 80


Socket­IO<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 />

Server­Socket: Externe Verbindung kann zu<br />

beliebigem Zeitpunkt hergestellt werden<br />

(Close)<br />

Evtl. Noch warten, bis Schreib­Puffer geleert sind<br />

Chr. Hochberger, Fakultät Informatik, TU Dresden 81


Asynchrones IO<br />

Socket wird auf Non­Blocking 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 IO­Aufruf möglich ist, wird ein<br />

Signal ausgelöst<br />

Signal­Behandlung 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 />

Signal­Handler:<br />

Bei eintreffendem Signal nicht klar, welcher Thread<br />

weiterarbeiten kann<br />

Select­Aufruf prüft, <strong>für</strong> welchen Socket welche<br />

Operationen möglich sind<br />

Interne Tabelle liefert Informationen, welcher Thread<br />

auf welchen Socket­Zustand 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 Signal­Handler erforderlich<br />

Chr. Hochberger, Fakultät Informatik, TU Dresden 84


IO­Threads <strong>für</strong> jeden Socket<br />

VM erzeugt 2 OS­Threads <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 Aufruf­Daten in interne Struktur<br />

Nativer Aufruf signalisiert betroffenem Thread<br />

Arbeitsauftrag (z.B.: Semaphor, System­Event)<br />

Nativer Aufruf wird beendet (PC <strong>zur</strong>ückstellen)<br />

IO­Thread erledigt Auftrag (mit synchronem IO)<br />

IO­Thread 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 IO­Threads<br />

Ein zusätzlicher IO­Thread:<br />

Wartet in Select auf Beendung möglicher IO­Aufrufe<br />

Wenn gewünschter Aufruf möglich, betroffenen <strong>Java</strong>­<br />

Thread als lauffähig markieren<br />

Problem:<br />

IO­Thread 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 Wurzel­Referenzen (Stack­Frames, Lokale<br />

Variablen, statische Klassen­Felder, ...)<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 />

Forward­Referenzen werden an alten Platz gestellt<br />

Weitere Referenzen auf altes Objekt werden durch<br />

Forward­Referenz 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


Echtzeit­Problematik<br />

Vorgestellte Verfahren sind nicht unterbrechbar<br />

Eintreffende Ereignisse werden erst bearbeitet, wenn<br />

GC beendet ⇒ inakzeptable Verzögerungen in<br />

Echtzeit­Systemen<br />

Zwei mögliche Lösungen:<br />

1. Unterbrechbare GC­Verfahren<br />

2. Inkrementelle GC­Verfahren, mit kurzen<br />

GC­Pausen (z.B. Train­Algorithmus, in <strong>Java</strong> SDK 1.3<br />

implementiert)<br />

Chr. Hochberger, Fakultät Informatik, TU Dresden 94


Unterbrechbare GC­Verfahren<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 />

Tri­Coloring<br />

➢ Zuordnung von Farben zu Objekten<br />

➢ Beschreibt Zustand des<br />

Erreichbarkeitsgraphen<br />

Chr. Hochberger, Fakultät Informatik, TU Dresden 95


Tri­Coloring<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 />

Lese­Barriere:<br />

Bei Zugriff auf weißes Objekt wird dieses grau gefärbt<br />

Verletzt weder starke noch schwache Invariante<br />

Schreib­Barriere:<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 GC­Lauf)<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 Objekt­Referenz auf null<br />

get() liefert die Objekt­Referenz (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


Referenz­Warteschlangen<br />

Verwalten Reference­Objekte, die freigegeben wurden<br />

Müssen beim Erzeugen des Reference­Objektes<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

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!