Java Virtual Machine - DBIS

Transcription

Java Virtual Machine - DBIS
Java Virtual Machine
Programmiermethodik
Eva Zangerle
Universität Innsbruck
Überblick
Einführung
Java – Ein erster Überblick
Objektorientierung
Vererbung und Polymorphismus
Ausnahmebehandlung
Pakete und Javadoc
Spezielle Themen
Generische Programmierung
Java Collection-Framework
Streams
Unit-Tests
Entwurfsmuster - Eine Einführung
GUI-Programmierung
JVM - Überblick
Java Virtual Machine
JVM - Struktur
Ausblick
Garbage Collection
Programmiermethodik - Java Virtual Machine
2
JVM - Überblick
Java allgemein
• Architektur von Java




Programmiersprache
Format für .class-Dateien
Java-API
JVM (Java Virtual Machine)
• Laufzeitumgebung






Abstrakte Maschine
Menge von Instruktionen
Speicherverwaltung
Dynamisches Laden von Klassen (class-loading)
Unterstützt Reflection (3. Semester)
Verwaltet Nebenläufigkeit (3. Semester)
• Diese Vorlesung

Basiert auf [Venners 2000]
Programmiermethodik - Java Virtual Machine
4
Programmierumgebung
Übersetzungsumgebung
Laufzeitumgebung
Source
A.java
B.java
Eigene class-Dateien
C.java
Java
Compiler
A.class
B.class
A.class
Lokal, über
Netzwerk etc.
C.class
Eigene class-Dateien
Programmiermethodik - Java Virtual Machine
B.class
C.class
Java
Virtual
Machine
Object.class
String.class
Java-API class-Dateien
5
Übersetzung – Interpretierung (Wiederholung)
• Übersetzung (Kompilierung)


Der Programmcode wird in einen Zielcode (z.B. Maschinencode)
umgesetzt.
Laufzeitumgebung führt diesen Code aus.
Vorteile

Nachteile

 Effizienz (sowohl Laufzeit als auch Speicher)
 Nicht portierbar (muss neu kompiliert werden)
• Interpretierung




Interpreter liest jede Instruktion.
Verifiziert den Code.
Gibt den korrekte Code an die Laufzeitumgebung weiter.
Vorteile

Nachteile
 Portierbarkeit
 Dynamisch, d.h. bei Änderungen muss die Applikation nicht neu gestartet
werden.
 Effizienz (langsam)
Programmiermethodik - Java Virtual Machine
6
Hybrider Ansatz (Java, C#, …)
• Idee

Aus dem Programmcode wird ein portabler Zwischencode erzeugt,
der auf verschiedenen Plattformen interpretiert werden kann.
MyProg.class
MyProg.class
MyProg.class
MyProg.class
Java-Plattform
für Linux
Java-Plattform
für Windows
Java-Plattform
für TV
Java-Plattform
für Toaster
Linux Rechner
Windows
Rechner
TV
Toaster
Programmiermethodik - Java Virtual Machine
7
Bytecode
• Zwischencode der von der JVM interpretiert wird.
• Ein beliebiger (gültiger) Java-Compiler muss gültigen
Bytecode erzeugen (.class-Dateien).
• Inhalt

Informationen über

Referenzen auf andere Klassen
 Klassenhierarchien
 Methodensignaturen
 Code von Methoden
 etc.
 Referenzen werden beim Ladeprozess aufgelöst.
• .class-Datei



Binärdatei
Immer big-endian (unabhängig von der darunterliegenden
Architektur; most significant bit in niedrigster Adresse)
Kompakt (z.B. für Netzwerkübertragung)
Programmiermethodik - Java Virtual Machine
8
Struktur einer .class-Datei
[Web 2012]
Programmiermethodik - Java Virtual Machine
9
Virtuelle Maschine
• Die virtuelle Maschine unterstützt



Plattformunabhängigkeit
Sicherheit
Mobilität (im Netzwerk)
• Die JVM ist eine abstrakte Maschine.


Spezifikation gibt einige Teile vor (z.B. JVM muss Bytecode
interpretieren können).
Implementierung wird aber offen gelassen (z.B. unterschiedliche
Ansätze den Bytecode zu interpretieren).
• Hauptaufgaben


Klassendateien laden
Bytecode in diesen Klassendateien ausführen
Programmiermethodik - Java Virtual Machine
10
Programmausführung
• Einfachster Ansatz (in Software)

Interpretierung des Bytecodes
• Just-in-time Übersetzung (JIT)


Bytecode wird in Maschinencode übersetzt (beim ersten Aufruf einer
Methode).
Erzeugter Code kommt in einen Cache, um später darauf zuzugreifen
(benötigt mehr Speicher!).
• Adaptive-Optimizer


Interpretierung
Oft benutzte Teile werden mit der Zeit (Monitoring) in
Maschinencode übersetzt.
• JVM in Hardware
Programmiermethodik - Java Virtual Machine
11
JVM in Software (1)
Java Virtual Machine
Eigene
Class-Dateien
Java-API
Class-Dateien
Class
loader
Bytecode
Execution engine
Aufruf nativer Methoden
Betriebssystem
Programmiermethodik - Java Virtual Machine
12
JVM in Software (2)
• Java-Programm interagiert mit dem Betriebssystem über
native Methoden.
• Java hat daher 2 Arten von Methoden


Java-Methoden (z.B. im eigenen Java-Programm implementiert)
Native Methoden (in C, C++, Assembler und entsprechend übersetzt)
 Beim Aufruf nativer Methoden lädt die JVM die entsprechenden dynamischen
Bibliotheken (plattformabhängig).
• Eigene native Methoden?


JNI (Java Native Interface)
Damit ist das entsprechende Programm nicht mehr
plattformunabhängig!
Programmiermethodik - Java Virtual Machine
13
JVM – Struktur
(Ein kurzer Überblick)
Virtuelle Maschine
• Spezifikation beschreibt das Verhalten an Hand von




Subsystemen
Speicherbereichen
Datentypen
Instruktionen
• Abstrakte Beschreibung



Beschreibt das Verhalten der JVM.
Beschreibt nicht die genaue innere Architektur!
Implementierung hängt vom Entwickler der JVM ab.
Programmiermethodik - Java Virtual Machine
15
Virtuelle Maschine (Architektur)
Class-Dateien
Method
area
Class loader
subsystem
Heap
Java
stacks
PC
registers
Native
method
stacks
Laufzeitdatenbereiche
Execution
engine
Programmiermethodik - Java Virtual Machine
Schnittstelle für native
Methoden
Bibliotheken
für native
Methoden
16
Virtuelle Maschine (Datenbereich)
• Jede JVM hat genau einen

Methodenbereich (method area)
 Bytecode
 Class-Daten

Heap
 Objektspeicher (alle Objekte werden hier abgelegt)
Klassen
-daten
Klassen
-daten
Klassen
-daten
Klassen
-daten
Objekt
Objekt
Klassen
-daten
Methodenbereich
Programmiermethodik - Java Virtual Machine
Objekt
Objekt
Objekt
Heap
17
Virtuelle Maschine (Thread-spezifische
Verwaltung)
• Daten zur Laufzeit
Thread 1
Thread 2
Thread 3
Thread 1
Stack
frame
Stack
frame
Stack
frame
Thread 2
Stack
frame
Stack
frame
Stack
frame
Stack
frame
Stack
frame
Thread 3
Stack
frame
PC-Register
Programmiermethodik - Java Virtual Machine
Java-Stacks
Thread 3
Native
Methoden
Stacks
18
Datentypen der JVM
float
Numerische
Typen
Floating-Point
Typen
double
byte
Primitive
Typen
boolean
Integrale
Typen
short
int
returnAddress
long
Klassentypen
Referenztypen
reference
char
Interface-Typen
Array-Typen
Programmiermethodik - Java Virtual Machine
19
Laden von Klassen (Class loading) in der JVM
Loading
• Lokalisierung der binären Repräsentation eines „Typs“
(Klasse, Interface)
• Laden der Daten
Linking
• Parsen des „Typs“ und Aufnahme in die aktuelle
Verwaltung der JVM
• Verifikation des Codes
• Vorbereitung
• Auflösung (von symbolischen Referenzen)
Initialization
• Aufruf des Initialisierers
Programmiermethodik - Java Virtual Machine
20
Wann wird eine Klasse geladen?
• Nicht festgelegt

Flexible JVM-Spezifikation
 Loading vor Linking
 Linking vor Initialization
 Initialization vor erster Verwendung („active use“)

„Active use“
 new-Anweisung, implizit bei String, Aufruf einer statischen Methode,
Initialisierung einer Subklasse, Aufruf der main-Methode usw.
• Normalerweise wird das Laden möglichst lange
hinausgezögert!


Ressourcen werden erst dann belegt, wenn sie wirklich benötigt
werden.
Ist aber keine Anforderung, d.h. Laden kann auch zu einem früheren
Zeitpunkt erfolgen!
Programmiermethodik - Java Virtual Machine
21
Klassenlader
• Damit der Bytecode von der JVM verarbeitet werden kann,
muss ein Klassenlader (class loader) die benötigte Klasse
laden.
• Alle Referenztypen (außer Arrays) werden entweder


durch den Bootstrap-Klassenlader oder
durch einen benutzerdefinierten Klassenlader geladen.
• Bootstrap-Klassenlader ist Teil der JVM.

Lädt alle Systemklassen
• Benutzerdefinierte Lader („normale“ Java-Klassen)


Werden von java.lang.ClassLoader abgeleitet.
Können bestimmte Zusatzaufgaben übernehmen.
 Caching
 Prefetching
 spezielle Überprüfungen
 etc.
Programmiermethodik - Java Virtual Machine
22
Method Area
• Nachdem der Klassenlader eine Klasse geladen hat, gibt er
Sie an die JVM weiter.
• Die JVM extrahiert Informationen und speichert diese
Informationen über den Typ in der so genannten Method
Area.
• Implementierung

Hängt vom JVM Designer ab (Datenstruktur, Größe, Verwaltung …).
• Für jeden Typ
Basisinformationen wie Name (voll qualifiziert), Name der
Superklasse, Unterscheidung ob Klasse oder Interface,
Zugriffsmodifikatoren, Liste von Interfaces (voll qualifiziert) …
 Zusätzlich: Constant Pool, Attribut- und Methodeninformationen, alle
statische Variablen (nicht Konstanten), Referenz auf den Klassenlader,
Referenz auf Klasse Class
 Methodentabellen (für schnellen Zugriff)

Programmiermethodik - Java Virtual Machine
23
Heap
• Innerhalb einer JVM gibt es einen Heap.


Alle Threads eines Programms teilen sich diesen.
Jedes Programm läuft aber in einer eigenen JVM-Instanz!
• Bei der Objekterzeugung (auch Array) wird Speicher vom
Heap angefordert



Die JVM hat eine Instruktion um Speicher anzufordern.
Es existiert aber keine Instruktion für die Freigabe.
Speicherfreigabe erfolgt durch den sogenannten Garbage-Collector.
Programmiermethodik - Java Virtual Machine
24
Objektrepräsentation (1)
• Objektrepräsentation ist nicht festgelegt.
• Beispiel: Monolithische Repräsentation
Ptr auf Klassendaten
Objektreferenz
Ptr auf Heap
Instanzdaten
Instanzdaten
Instanzdaten
Heap
Klassen
-daten
Methodenbereich
Programmiermethodik - Java Virtual Machine
25
Objektrepräsentation (2)
• Geteilte Repräsentation
Handle-Pool
Objektreferenz
Ptr auf Heap
Ptr auf Objektpool
Ptr auf
Klassendaten
Objektpool
Instanzdaten
Instanzdaten
Heap
Klassen
-daten
Methodenbereich
Programmiermethodik - Java Virtual Machine
26
Spezielles Beispiel mit Arrays
int [][] ar =
new int [2][2];
Ptr auf Klassendaten
length (=2)
ar[0] (Arrayreferenz)
ar[1] (Arrayreferenz)
Ptr auf Klassendaten
length (=2)
ar[0][0] (int)
ar[0][1] (int)
ar (Arrayreferenz)
Ptr auf Klassendaten
length (=2)
ar[1][0] (int)
ar[1][1] (int)
Heap
Klassen
daten für
[[ ]]
Klasse
ndaten
für [ ]
Methodenbereich
Programmiermethodik - Java Virtual Machine
27
Vererbung
• Code für Methoden wird bei der Vererbung nicht dupliziert!

Z.B. Klasse C1 und C2 teilen sich den Code von m1()
C1
~x : int
+m1()
C1 o1 = new C1();
C2 o2 = new C2();
o2.m1();
Code von C1
o2.x = 10;
o2.y = 10;
C2
C2 hat ein lokales x!
Nicht gemeinsam!
~y : int
+m2()
Programmiermethodik - Java Virtual Machine
28
Vererbung (Implementierung)
Referenz auf Superklasse
Methodenbereich
Instanzenraum
x
m2()
m1()
x
y
Speicher
C1
C2
o1
Programmiermethodik - Java Virtual Machine
o2
29
Dynamisches Binden (1)
C1
~x : int
+m1()
+is Null() : boolean
C2
~y : int
+m2()
+is Null() : boolean
Programmiermethodik - Java Virtual Machine
C1 c;
C1 o1 = new C1();
C2 o2 = new C2();
boolean b;
…
if(…)
c = o1;
else
Dynamisches Binden!
c = o2;
b = c.isNull();
30
Dynamisches Binden (2)
• Jede Klasse hat eine so genannte Dispatch-Tabelle.



Ziel: Operation mit Methode verknüpfen.
Tabelle hat eine Liste der Methoden, die in der Klasse implementiert
werden und einen Pointer auf die Superklasse.
Lookup zur Laufzeit – Performance!?
Dispatch-Tabelle
m1()
isNull()
c.isNull()
m2()
isNull()
x
x
y
Speicher
C1
C2
o1
Programmiermethodik - Java Virtual Machine
o2
31
Stack
• Für jeden Thread wird ein eigener Stack verwaltet.

Stack verwaltet so genannte Frames.
• Die JVM führt nur 2 Operationen auf den Stack direkt aus.

push und pop (von Frames)
• Aktuelle Ausführung
current
 current
 current
 current

method (Methode die aktuell ausgeführt wird)
frame
class (Klasse, in der die Methode definiert ist)
constant pool (Konstanten der aktuellen Klasse)
• JVM verwaltet die Ausführung.
• Wenn die JVM auf Operationen trifft, die auf Daten im
aktuellen Frame operieren, dann führt sie diese im aktuellen
Frame aus.
• Tatsächliche Verwaltung des Stacks ist
implementierungsabhängig!
Programmiermethodik - Java Virtual Machine
32
Frame
• Wird beim Aufruf einer Methode erzeugt.

Wenn ein Thread eine Methode aufruft.
• Die ausführende Methode speichert Parameter, lokale
Variablen, Zwischenresultate und weitere Daten in diesem
Frame.
• Beendigung einer Methode


Normal
Durch Ausnahme
• Bei Beendigung nimmt die JVM den Frame vom Stack und
verwirft ihn.
• Der Frame der vorhergehenden Methode (aufrufenden
Methode) wird zum current frame.
Programmiermethodik - Java Virtual Machine
33
Aufbau eines Frames
• 3 Bereiche

Lokale Variablen

Operandenstack

Frame-Daten
 Array
 Über Index Zugriff auf Variablen
 Array nach dem Stack-Prinzip verwaltet
 Arbeitsplatz für die JVM
 JVM hat daher eine Stack-basierte Architektur!
 Constant pool resolution
 Verwaltung von Ausnahmen
• Größe


Speicherplatzanforderung für lokale Variablen und Operandenstack
wird zur Übersetzungszeit berechnet und für jede Methode in die
class-Datei eingefügt (Größe der Frame-Daten
implementierungsabhängig).
Beim Aufruf einer Methode werden diese Daten verwendet.
Programmiermethodik - Java Virtual Machine
34
JVM-Instruktionen (1)
• JVM-Instruktion


opcode (1 Byte) für die Instruktion die ausgeführt werden muss
0 oder mehrere Operanden (1 oder mehrere Bytes) für die Operation
• Innere Schleife der JVM execution engine (ohne Ausnahmen)
do {
fetch an opcode;
if (operands) fetch operands;
execute the action for the opcode;
} while (there is more to do);
Programmiermethodik - Java Virtual Machine
35
JVM-Instruktionen (2)
• Die meisten Operationen nehmen Operanden vom Stack und
geben das Resultat auf den Stack.
• Viele Instruktionen haben mehrere Versionen.


Abhängig von den Typen der Operanden
Unterscheidung durch Präfix
 i,l,f,d,b,s,c,a

Beispiele
 iload – Integer laden
 dload – Double laden
 ….
Programmiermethodik - Java Virtual Machine
36
JVM-Instruktionen (3)
• Unterschiedliche Typen








Laden/Speichern (z.B. load, store, push, lcd, wide …..)
Arithmetik/Logische Operationen (z.B. add, sub, mul, shl, shr, or,
xor …..
Typkonvertierung (z.B. i2l, i2f, i2b, …)
Objekterzeugung/-manipulation (z.B. new, newarray, aload,
astore, …)
Operandenstack-Management (z.B. pop, pop2, swap ….)
Kontrollfluss (z.B. ifeq, iflt, ifle, ifne, tableswitch,
lookupswitch, ..)
Methodenaufruf (z.B. invokevirtual, invokeinterface,
invokestatic, invokespecial ….)
Ausnahmen/finally
Programmiermethodik - Java Virtual Machine
37
Parameter (Beispiel)
public class Example {
public static int runClassMethod(int i, long l, float f, double d,
Object o, byte b) {
return 0;
}
public int runInstanceMethod(char c, double d, short s, boolean b) {
return 0;
}
}
runClassMethod()
runInstanceMethod()
index
type parameter
0
int
int i
1
long
long l
3
float
float f
4
double
double d
6
7
reference
int
Object o
byte b
Programmiermethodik - Java Virtual Machine
index
type parameter
0
1
reference
int
hidden this
char c
2
double
double d
4
5
int
int
short s
boolean b
38
Operandenstack (Beispiel)
iload_0
iload_1
iadd
istore_2
Vor der
Ausführung
lokale
Variablen
0
1
2
100
98
OperandenStack
Programmiermethodik - Java Virtual Machine
Nach
iload_0
0
1
2
100
98
100
Nach
iload_1
0
1
2
100
98
100
98
Nach
iadd
0
1
2
100
98
Nach
istore_2
0
1
2
100
98
198
198
39
Bytecode anzeigen – javap
• javap ist ein Disassembler
Defaultmäßig gibt er nur die öffentliche Schnittstelle aus.
 -c gibt den Code für alle Methoden aus.
 -l gibt den Code für alle Variablen aus.
 -private zeigt alle Variablen und Klassen.
 -s für interne Typsignaturen.

• Weitere Informationen:

http://download.oracle.com/javase/1,5.0/docs/tooldocs/windows/javap.html
Programmiermethodik - Java Virtual Machine
40
Beispiel (1)
public class FactorialTest {
public static int factorial(int n) {
return (n == 0) ? 1 : n * factorial(n - 1);
}
}
public static void main(String[] args) {
for (int i = 1; i < 10; i++) {
System.out.println(factorial(i));
}
}
javap –c FactorialTest:
Compiled from "FactorialTest.java"
public class FactorialTest {
public FactorialTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
Programmiermethodik - Java Virtual Machine
41
Beispiel (2)
}
public static int factorial(int);
Code:
0: iload_0
1: ifne
8
4: iconst_1
5: goto
16
8: iload_0
9: iload_0
10: iconst_1
11: isub
12: invokestatic #2 // Method factorial:(I)I
15: imul
16: ireturn
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iload_1
3: bipush
10
5: if_icmpge
24
8: getstatic
#3 // Field
java/lang/System.out:Ljava/io/PrintStream;
11: iload_1
12: invokestatic #2 // Method factorial:(I)I
15: invokevirtual #4 // Method
java/io/PrintStream.println:(I)V
18: iinc
1, 1
21: goto
2
24: return
Programmiermethodik - Java Virtual Machine
42
Java 7
• Bytecode für die JVM kann im Prinzip von beliebigen
Programmiersprachen kommen (sofern ein Compiler
existiert, der gültigen Bytecode erzeugt).

Es existieren zum Beispiel Bytecode-Compiler für Python oder Ruby.
 Problem: Diese Sprachen sind dynamisch typisierte Sprachen!
Java und die JVM sind aber auf statische Typspezifizierung zur
Übersetzungszeit ausgelegt.
 Nur mit Tricks (und Performance-Verlust) können dynamisch
typisierte Sprachen in Bytecode übersetzt werden.

• Daher wurde eine neue Bytecode-Instruktion
(invokedynamic) eingeführt (wird aber vom Java-Compiler
ignoriert).


Aufruf einer beliebigen Methode ist erlaubt, ohne dass geprüft wird,
zu welcher Klasse diese Methode gehört, von welchem Typ ihr
Returnwert ist oder welche Methodenparameter sie verwendet.
Erhöht die Performance für dynamisch typisierte Sprachen.
Programmiermethodik - Java Virtual Machine
43
Bytecode in Quellcode umwandeln (1)
• Ein Decompiler wandelt Java-Klassendateien in JavaQuellcodedateien zurück.
• Reverse Engineering
• Decompiler gibt es auch für andere Sprachen, in Java ist aber
das Wiederherstellen des ursprünglichen Codes recht
einfach.
• Bytecode enthält viele Hinweise für den Interpreter.
• Ein Decompiler benötigt lediglich die Klassendatei.



Einige Decompiler arbeiten auch direkt mit einem jar-Archiv.
Aus dem Java-Bytecode für eine Methode baut er dann einen
Kontrollfluss-Graphen auf.
Der Decompiler versucht Ausdrücke zu erkennen, die bei der
Übersetzung bestimmter Sprachkonstrukte entstanden sein müssten.
Programmiermethodik - Java Virtual Machine
44
Bytecode in Quellcode umwandeln (2)
• Wann ist das legal?



Bei eigenem Programm
Solange fremde Software nicht verändert wird (?)
Nicht mehr, wenn fremde Software als Eigenleistung verkauft wird
!!!!!!
Programmiermethodik - Java Virtual Machine
45
Jad – Ein Decompiler
• Ist ein frei verfügbarer Decompiler




Sehr schnell (in C++ geschrieben)
Kann auch Bytecode anzeigen.
Kann auch „verschleierten“ Code teilweise rekonstruieren.
Wird aber nur den gegebenen Code rekonstruieren.
 Generics sind dann zum Beispiel nicht mehr vorhanden!
• Aufruf



jad example.class (Ausgabe in example.jad)
jad -sjava example.class (Ausgabe in example.java)
Weitere Infos: http://www.varaneckas.com/jad
• Rückübersetzung erschweren


Sogenannte Obfuscater verändern den Code.
Decompiler kann dann oft keine richtige Entscheidung treffen.
Programmiermethodik - Java Virtual Machine
46
Garbage-Collection
Speicherplatzfreigabe
• In C


free() gibt belegten Speicherplatz frei.
Fehleranfällig!
• In C++


Konstruktor/Destruktor (Erzeugung, Freigabe)
Auch fehleranfällig!
• In einem objektorientierten System sollten Objekte verfügbar
sein, solange sie benutzt werden.
• Die Laufzeitumgebung sollte nicht mehr benutzte Objekte
entfernen (und damit den Speicherplatz freigeben).
Programmiermethodik - Java Virtual Machine
48
Garbage
• Nicht benutzte Objekte



Kein anderes Objekt hat eine Referenz auf dieses Objekt.
Niemand kann eine Nachricht an dieses Objekt senden.
Objekt ist nicht mehr nützlich („Müll“).
• Garbage-Collector



Ist ein spezieller Prozess.
Sammelt periodisch nicht benutzte Objekte ein und gibt den Speicher
frei.
Erweiterungen werden noch besprochen.
• JVM


Art der Garbage-Collection ist nicht explizit vorgegeben.
Es muss nicht einmal ein Garbage-Collector vorhanden sein.
Programmiermethodik - Java Virtual Machine
49
Beispiel
Complex c1, c2;
c1 = new Complex();
c1 = c2;
c1
c2
new Complex()
Complex
Speicher
c1
c2
new Complex()
Complex
Speicher
Garbage!!
Verschiedene Ansätze für Garbage-Collection!
Programmiermethodik - Java Virtual Machine
50
Garbage-Collection allgemein
• 2 Gründe für Garbage-Collection

Speicher freigeben
 JVM kann diese Aufgabe übernehmen (automatisieren).

Fragmentierung des Heaps unterbinden bzw. verringern.
 Für eine neue Allokation wird zusammenhängender Speicher benötigt.
 Freigabe mehrerer Objekte muss nicht zusammenhängenden freien Speicher
freigeben.
• Nachteil


Zusätzlicher Speicheraufwand
CPU-Aufwand wenn der Garbage-Collector anläuft
 Längere Laufzeit
• Unterschiedliche Algorithmen


Basierend auf Referenzzähler
Tracing-Algorithmen (basierend auf Erreichbarkeitsgraphen)
Programmiermethodik - Java Virtual Machine
51
Reference Counting
• Jedes Objekt hat einen Zähler rc.




Bei der Erzeugung: rc=1
Kommt eine neue Referenz hinzu: rc++
Wird eine Referenz entfernt: rc -Wenn rc==0 dann kann der Garbage-Collector das Objekt
einsammeln.
• Vorteile


Verteilung der Last (aber viel Last!)
Gute Lokalität, schnelle Reaktion
rc(O1) == 1
Programm
O1
P
• Nachteile


Zusätzlicher Speicherbedarf
Zyklen werden nicht erkannt!
O2
rc(O2) == 1
 O1 und O2 werden nicht mehr von P (im Programm) referenziert.
 Referenzieren sich aber gegenseitig, d.h. rc==1.
Programmiermethodik - Java Virtual Machine
52
Mark-and-Sweep
• Definiert Wurzel und überprüft Erreichbarkeit.


Wurzel (root set) = Objekte die immer existieren
Objekte, die man von der Wurzel aus nicht erreichen kann, werden
entfernt.
• Mark and Sweep




Graph von der Wurzel aus aufbauen.
Alle erreichten Objekte markieren.
Entferne nicht markierte Objekte.
Setze alle markierten Objekte auf nicht-markiert.
• Vorteil

Kein Problem mit Zyklen
• Nachteile


Fragmentierung
Aufwand proportional zur Heap-Größe
Programmiermethodik - Java Virtual Machine
53
Stop-and-Copy (1)
• Heap wird in 2 gleich große Bereiche unterteilt.

fromspace und tospace
• Bei einem Durchlauf werden die Rollen der Bereiche
vertauscht.
• Bei einem Durchlauf werden die aktuellen Teile vom alten
Bereich (fromspace) in den neuen Bereich (tospace)
kopiert – Programmvariablen benutzen den neuen Bereich.
• Garbage im fromspace wird einfach entfernt.
• Im tospace wird beim Kopieren automatisch
Fragmentierung unterbunden.
Programmiermethodik - Java Virtual Machine
54
Stop-and-Copy (2)
1
• Beispiel
frei
2
3
4
5
6
7
8
9
frei
unbenutzt unbenutzt unbenutzt
frei
…
frei
frei
unbenutzt unbenutzt unbenutzt
Stop
and
Copy
unbenutzt
Stop
and
Copy
• Vorteile


Allokation schnell und billig
Keine Fragmentierung
• Nachteile


50% des Heaps nicht benutzt
Langlebige Objekte werden immer wieder kopiert.
Programmiermethodik - Java Virtual Machine
55
Generational Collectors (1)
• Ein Problem (neben der nicht effizienten Auslastung des
Speichers) von Stop-and-Copy ist, dass jedes erreichbare
Objekt immer wieder kopiert werden muss.
• Dies kann verbessert werden, wenn folgende empirischen
Erkenntnisse berücksichtigt werden:


Die meisten Objekte haben eine sehr kurze Lebenszeit und werden
sehr bald nach der Erzeugung nicht mehr benötigt.
Einige Objekte haben eine sehr lange Lebenszeit und sind der
Hauptgrund für die Ineffizienz von Stop-and-Copy (werden immer
wieder kopiert).
Programmiermethodik - Java Virtual Machine
56
Generational Collectors (2)
• Vorgehensweise (allgemein)






Heap wird in 2 oder mehrere Sub-Heaps unterteilt.
Jeder Sub-Heap verwaltet eine „Generation“ von Objekten.
Die jüngste Generation wird am öftesten überprüft.
Die meisten Objekte werden sehr schnell freigegeben und können
eingesammelt werden.
Übersteht ein Objekt eine bestimmte Anzahl von Garbage-CollectionDurchläufen, dann wird es in den nächsten Heap verschoben.
Je älter die Generation in einem Heap, desto seltener wird dieser
Heap überprüft.
• Kombination mit herkömmlichen Methoden


Mark-and-Sweep
Stop-and-Copy
Programmiermethodik - Java Virtual Machine
57
Weitere Algorithmen, Methoden etc.
• Garbage-Collection kann sehr aufwändig sein.




Algorithmus benötigt bestimmte Zeit für das Abarbeiten des Heaps
(der Heaps).
Laufendes Programm wird angehalten („Stop the world“-Prozess).
Großes Problem bei interaktiven Programmen.
Sehr großes Problem bei Echtzeitsystemen.
• Inkrementelle Anwendung


Algorithmus bearbeitet nicht den gesamten Heap (nur Teile davon).
Die Zeit für den kleineren Durchlauf kann leichter nach oben
beschränkt werden.
• Heapgrößen für unterschiedliche Generationen festlegen.



Die Zeit für den Durchlauf eines Heaps kann beschränkt werden.
Die „älteste“ Generation darf aber nicht beschränkt sein.
Für diese muss man sich einen speziellen Algorithmus überlegen.
Programmiermethodik - Java Virtual Machine
58
Garbage-Collection und Programmierer
• Garbage-Collection ist nicht vorhersagbar!


In viele Fällen macht sich die Garbage-Collection nicht bemerkbar.
Aber schlecht für Echtzeitsysteme!
• Allgemeine Regeln


Nur notwendigen Speicher anfordern!
Nicht Referenzen horten!
 Z.B. nicht benötigte Einträge in einem Array auf null setzen!
• Aufruf von System.gc()


Manchmal sinnvoll
Was macht der Garbage-Collector an dieser Stelle?
 “Calling the gc method suggests that the Java Virtual Machine expend effort
toward recycling unused objects in order to make the memory they currently
occupy available for quick reuse. When control returns from the method call, the
Java Virtual Machine has made a best effort to reclaim space from all discarded
objects.”
Programmiermethodik - Java Virtual Machine
59
Objektreferenzen
• Unterschiedliche Arten von Referenzen:
• Stufen der Erreichbarkeit

Strongly reachable




Softly reachable
Weakly reachable
Phantomly reachable
Unreachable (bisher besprochen - wenn keine Referenz)
 Bisher besprochen
 Garbage-Collector kann Objekte mit solchen Referenzen nicht einsammeln.
Programmiermethodik - Java Virtual Machine
60
Soft-Referenzen
• Objekte die darüber referenziert werden, werden erst dann
eingesammelt, wenn der Speicher knapp wird.
• Spezifikation verlangt nur, dass diese Objekte eingesammelt
werden, bevor es zu einem OutOfMemory-Error kommt.

Soft-Referenzen werden für Caching verwendet.
• Ältere Objekte werden zuerst eingesammelt.
• Mit der Methode get() bekommt man den Inhalt (das
Objekte) der Referenz oder null, wenn das Objekt vom
Garbage-Collector eingesammelt wurde
• Beispiel (Ausgeben des Inhalts)
SoftReference<Integer> i = new SoftReference<Integer>(1000);
System.out.println(i.get());
Programmiermethodik - Java Virtual Machine
61
Weak-Referenzen
• Objekte die darüber referenziert werden, werden
eingesammelt, wenn sie nur mehr über Folgen von
Referenzen referenziert werden, die alle zumindest eine
Weak-Referenz enthalten.
• Sobald der Garbage-Collector anläuft, werden diese Objekte
eingesammelt.
• Beispiel
WeakReference<Integer> i2 = new WeakReference<Integer>(1200);
System.out.println(i2.get());
Programmiermethodik - Java Virtual Machine
62
Soft- und Weak-Referenzen (Vergleich)
• Beispiel (in Verbindung mit unterschiedlichen Referenzen)
SoftReference<Integer> i = new SoftReference<Integer>(1000);
WeakReference<Integer> i2 = new WeakReference<Integer>(1200);
System.out.println(i.get()); // 1000
System.out.println(i2.get()); // 1200
System.gc();
System.out.println(i.get()); // 1000
System.out.println(i2.get()); // null
Programmiermethodik - Java Virtual Machine
63
Phantom-Referenzen
• Auf diese kann man nicht mehr zugreifen.
• Ermöglichen „sauberes“ Einsammeln der Objekte.
• Ähnlich wie finalize-Methode, aber flexibler.
• get() liefert immer null.
• Anwendungsgebiete sind Abschlussaktionen allgemeiner Art,
die sich nicht auf ein bestimmtes Exemplar beziehen und bei
denen es ausreicht, festzustellen, dass ein Objekt finalisiert
wurde, ohne zu wissen, welches konkrete Objekt es war oder
zu welcher Klasse es gehörte.
Programmiermethodik - Java Virtual Machine
64
Referenzpfade
• Objekte können vom root set ausgehend über mehrere Pfade
erreicht werden.
• Die schwächste Referenz auf dem stärksten Pfad bestimmt
die Erreichbarkeit.
Root set
PhantomReferenz
WeakReferenz
SoftReferenz
Programmiermethodik - Java Virtual Machine
Some
Object
Erreichbarkeit von
Some Object: Soft
65
finalize
• Methode finalize() kann in jeder Klasse überschrieben
werden (von Object geerbt).
• Wird vom Garbage-Collector ausgeführt.

Daher kann man nie genau sagen, wann finalize() ausgeführt
wird.
• Sollte vermieden werden (wenn nicht unbedingt notwendig)!
• Sollte möglichst wenig Zeit und Ressourcen verbrauchen!
• Allgemeine Form
protected void finalize() throws Throwable {
try {... /*Freigabe etc.*/ }
finally { super.finalize(); }
}
Programmiermethodik - Java Virtual Machine
66
Garbage-Collection in der JVM (1)
• JVM



Mehrere Algorithmen
Generational Collection
Standardeinstellung meist ausreichend
• Generations

Default-Anordnung sieht ungefähr so aus
Programmiermethodik - Java Virtual Machine
67
Garbage-Collection in der JVM (2)
• Parameter


Garbage-Collection kann parametrisiert werden (bei Aufruf von java).
Beispiele
 -Xms: Anfängliche Heap-Größe
 -Xmx: Maximale Heap-Größe
 -XX:MinHeapFreeRatio: Minimales Verhältnis freier/belegter Speicher
 -XX:MaxHeapFreeRatio: Maximales Verhältnis freier/belegter Speicher
 Weitere Beispiele:
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html


Parameter für Generationen
Parameter für unterschiedliche Typen
Programmiermethodik - Java Virtual Machine
68
Ausblick
• JVM



Umfangreiche Spezifikation
Programmierer muss sich nur an die Spezifikation halten, kann aber
selbst viele Implementierungsentscheidungen treffen.
JVM ist mittlerweile recht ausgereift, d.h. recht stabil.
• JVM und Java


Ursprünglich starke Verbindung zwischen JVM und Java.
Mittlerweile gibt es viele andere Sprachen, die JVM-Bytecode
erzeugen.
• Weitere Informationen

Garbage Collection unterliegt ständigen Umbauten:
(Java7=G1; Java8=Metaspace)


http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html
Programmiermethodik - Java Virtual Machine
69
Literatur
Literatur
• [Venners 2000] Bill Venners, Inside the Java 2 Virtual
Machine, McGraw-Hill Companies , 2000, online
(ausgewählte Kapitel):
http://www.artima.com/insidejvm/ed2/
• [Web 2012]
http://jakarta.apache.org/bcel/images/classfile.gif
Programmiermethodik - Java Virtual Machine
71