3 Der Lebenszyklus eines Typs

Werbung
Seminar Softwareentwicklung
Dynamisches Laden
und Binden in Java
Reinhard Stumptner
Dynamisches Laden und Binden in
Java




2
Der Lebenszyklus eines Typs
Der Lebenszyklus eines Objekts
Dynamisches Binden
Eigene Lader
Reinhard Stumptner
Der Lebenszyklus eines Typs
3
Der Lebenszyklus eines
Typs
Reinhard Stumptner
Class-File laden

Drei Hauptaktivitäten:
–
–
–



4
Erzeugen eines binären Datenstroms
umwandeln dieser Daten in interne Strukturen (Method Area)
Erzeugen einer Instanz von java.lang.Class
Die Class - Instanz dient als Interface zwischen Programm und
internen Datenstrukturen (Method Area)
Geladen wird entweder mit dem Bootstrap Class Loader (Teil
der JVM) oder mit benutzerdefinierten Ladern
Benutzerdefinierte Lader könnten z.B. Dateien von einem
Netzwerk laden oder verschlüsselte Dateien laden
Der Lebenszyklus eines
Typs
Reinhard Stumptner
Class-File verifizieren


Entspricht es der Semantik von Java?
Prüfungen in der Verifikationsphase:
–
–
–
–
–
5
Von final Klassen wurde nicht geerbt
Final Methoden wurden nicht überschrieben
Keine inkompatiblen Methodendeklarationen
Einträge im Constant Pool sind untereinander
konsistent
Integritätsprüfung des Bytecodes
Der Lebenszyklus eines
Typs
Reinhard Stumptner
Vorbereiten des Typs


6
Für die Klassenvariablen wird Speicher
reserviert und mit „0“ initialisiert
Anlegen zusätzlicher Datenstrukturen
(Methodentabelle)
Der Lebenszyklus eines
Typs
Reinhard Stumptner
Constant Pool auflösen
7
Der Lebenszyklus eines
Typs
Reinhard Stumptner
Initialisieren des Typs



Class Variable Initializer:
class ClassInit {
static int i=3*5*Math.random();
}
Static Initializer:
class StaticInit {
static int i;
static {
i=13*Math.random();
}
}
2 Schritte der Initialisierung:
–
–

8
Initialisieren der direkten Superklasse (wenn nicht bereits initialisiert)
Ausführen von <clinit>() (mit enthaltenen Initializern)
Initialisierung vor erster aktiver Verwendung
Der Lebenszyklus eines
Typs
Reinhard Stumptner
Initialisieren des Typs

Aktive vs. Passive Verwendung
class A {
static int x=10*Math.random();
static {System.out.println(“init A”);}
}
class B extends A {
static int y=20*Math.random();
static {System.out.println(“init B”);}
}
class C {
static { System.out.println(“init C”);}
public static void main(String[] args) {
int z=B.x; // aktive Verwendung von A,
// passive Verwendung von B
System.out.println(“finished”);
}
}
Ausgabe:
9
init C init A finished
Der Lebenszyklus eines
Typs
Reinhard Stumptner
Der Lebenszyklus eines Objekts

Das Erzeugen einer Instanz stellt den Beginn des Lebenszyklus eines
Objekts dar, Garbage Collection (bzw. finalize()) dessen Ende
Method Area
Heap
Class-Instanz für A
Typinformation von A
new A()
10
Der Lebenszyklus eines
Objekts
Reinhard Stumptner
Instanzieren einer Klasse

vier Arten:
–
new()
A
–
obj = new A();
newInstance()(java.lang.Class)
Class myClass=Class.forName(Name);
Name obj = (Name) myClass.newInstance();
–
clone()
A
–
11
obj2 = obj.clone();
Deserialisieren eines Objekts mit getObject(), enthalten
in java.io.ObjectInputStream
Der Lebenszyklus eines
Objekts
Reinhard Stumptner
Instanzieren einer Klasse

Reservieren von Speicher am Heap
–
–


12
für Instanzvariablen der Klasse und die der
Superklassen
default Initialwert (0)
Instanzvariablen mit den richtigen
Startwerten versehen
zumindest eine <init>() Methode wird
erzeugt (Konstruktor)
Der Lebenszyklus eines
Objekts
Reinhard Stumptner
Instanzieren einer Klasse
public class Konstruktoren {
public String name;
public int min=0, max=10; (Initializer)
public Konstruktoren(String name) {
// Aufruf des default Konsruktors von Object,
// Ausführen von „min=0“, „max=10“
this.name=name;
}
public Konstruktoren(String name, int min) {
this(name); // kein Aufruf des Konsruktors von Object
this.min=min;
}
}
13
Der Lebenszyklus eines
Objekts
Reinhard Stumptner
Freigeben eines Objekts


14
Programme können Speicher für Objekte am
Heap reservieren, aber nicht explizit
freigeben  Garbage Collector
Besitzt eine Klasse eine finalize()
Methode, wird diese, vor Freigeben des
Speichers des Objekts, ausgeführt
Der Lebenszyklus eines
Objekts
Reinhard Stumptner
Freigeben eines Typs

15
Typen werden, wenn
sie nicht mehr
benötigt werden,
freigegeben, d.h.
wenn sie nicht
erreichbar sind
Der Lebenszyklus eines
Objekts
Reinhard Stumptner
Dynamisches Binden – The Linking
Model




16
Auflösen symbolischer Referenzen
Dynamische Erweiterung
Parent-Delegation Model
Constant Pool Resolution
Reinhard Stumptner
Auflösen symbolischer
Referenzen



17
.class Dateien werden beim Kompilieren
durch symbolische Referenzen im Constant
Pool verbunden
Diese müssen vor Programmstart aufgelöst
und durch direkte Referenzen ersetzt werden
(constant pool resolution)
frühe – späte Resolution
The Linking Model
Reinhard Stumptner
Dynamische Erweiterung


Java Applikationen können zur Laufzeit
entscheiden, welche Typen geladen und gebunden
werden sollen
Zwei Mechanismen:
–
java.lang.Class: (hier wird immer gebunden)

–
java.lang.ClassLoader: (Binden offen)

18
public static Class forName (String className,
boolean initialize, ClassLoader loader) throws
ClassNotFoundException;
protected Class loadClass (String name,
boolean resolve) throws
ClassNotFoundException;
The Linking Model
Reinhard Stumptner
Parent-Delegation Model



19
Versucht ein Lader einen Typ zu laden, gibt
er diesen Auftrag immer zuerst an seine
Superklasse weiter. Am Ende dieser
Aufrufkette steht der Bootstrap Class Loader
Lader, der eine Klasse lädt: definierender
Class Loader
Lader, der einen anderen Lader mit dem
Ladeprozess beauftragt: initialisierender
Class Loader
The Linking Model
Reinhard Stumptner
Constant Pool Resolution


Der Constant Pool ist
mit Symboltabellen
vergleichbar
Struktur eines
Eintrags:
CONSTANT_Class_Eintrag {
byte Tag(=7);
short Namensindex;
}
20
Constant Pool
Resolution
Typen der Einträge im Konstantenpool
Reinhard Stumptner
Resolution von Klassen und Interfaces
Auflösen einer symbolischen Referenz auf eine Klasse:
1. C und Superklassen laden
–
–
–
Wurde C noch nicht geladen, sucht die JVM nach
C.class
C binden, verifizieren und vorbereiten
binäre Datenstruktur von C prüfen
C wird initialisiert
3. Zugriffsrechte werden überprüft
Verwendeter Lader: der, mit dem referenzierende
Klasse geladen wurde
2.
21
Constant Pool
Resolution
Reinhard Stumptner
Resolution von Array Klassen



Anzahl der Dimensionen und Basistyp aus
dem field descriptior auslesen.
Anzahl von „[“ gibt Dimensionen an
Basistyp:
–
primitiver Datentyp (erstes Zeichen ist kein „L“)

–

22
Z….boolean, B….byte, I….int, …
Referenztyp  diesen laden, binden
Von Bootstrap geladen
Constant Pool
Resolution
Reinhard Stumptner
Resolution von Feldern und Methoden



23
CONSTANT_Fieldref: Klassen- oder
Instanzvariable
CONSTANT_Methodref: Methode einer
Klasse
Klassenvariablen, statische Methoden
werden durch Referenz auf Typinformationen
aufgelöst
Constant Pool
Resolution
Reinhard Stumptner
Resolution von Feldern und Methoden

Direkte Referenzen von Instanzvariablen und
–methoden entsprechen einem Offset
class A {
int x;
String s=“Hello“;
public void getX(){return x;}
}
24
Constant Pool
Resolution
A- Instanz
0
Zeiger in Method Area
1
x
2
s
Reinhard Stumptner
Resolution von Feldern und Methoden
Methodentabelle von A:
25
0
Zeiger auf wait()
1
Zeiger auf clone()
2
Zeiger auf equals()
3
Zeiger auf finalize()
4
Zeiger auf getClass()
5
Zeiger auf hashCode()
6
Zeiger auf notify()
7
Zeiger auf notifyAll()
8
Zeiger auf toString()
9
Zeiger auf getX()
Constant Pool
Resolution
Typinformation von
Object
Typinformation von A
Reinhard Stumptner
Resolution von Strings

CONSTANT_String (java.lang.String),
verweist auf CONSTANT_Utf8

Gleiche Strings verweisen auf selbe Instanz
der Klasse String
Resolution: String- Objekt wird erzeugt und
als direkte Referenz eingetragen

26
Constant Pool
Resolution
Reinhard Stumptner
Resolution von anderen Elementen im
Constant Pool


27
CONSTANT_Integer, CONSTANT_Long,
CONSTANT_Float und CONSTANT_Double werden
direkt dargestellt:
CONSTANT_Integer {
byte tag=3;
int wert;
}
CONSTANT_NameAndType und CONSTANT_Utf8
werden nicht aufgelöst, sie können von anderen
Einträgen referenziert werden
Constant Pool
Resolution
Reinhard Stumptner
Beispiel: Salutation- Applikation
class Salutation {
private static final String hello=“Hello, world!“;
private static final String greeting=“Greetings, planet!“;
private static final String salutation=“Salutations, orb!“;
private static int choice=(int)(Math.random()*2.99);
public static void main(String[] args) {
String s =hello;
if (choice==1) s=greeting;
else if (choice==2) s=salutation;
System.out.println(s);
}
}
Beim Initialisieren wird sichergestellt, dass alle Superklassen von Salutation
initialisiert wurden.
28
Constant Pool
Resolution
Reinhard Stumptner
Beispiel: Salutation- Applikation


29
Verifikation:
– Bytecode ist syntaktisch korrekt
– Salutation entspricht der Java Semantik
– Salutation wird die JVM nicht zum Absturz bringen (Jumps)
Vom Compiler wurde .class Datei mit Constant Pool erzeugt
Constant Pool
Resolution
Reinhard Stumptner
Beispiel: Salutation- Applikation
Symbolische Referenz zu “Hello, world!“
30
Constant Pool
Resolution
Reinhard Stumptner
Beispiel: Salutation- Applikation
Symbolische Referenzen von Salutation zu Math.random()
31
Constant Pool
Resolution
Reinhard Stumptner
Beispiel: Salutation- Applikation
Symbolische Referenz zu System.out
32
Constant Pool
Resolution
Reinhard Stumptner
Beispiel: Salutation- Applikation
Symbolische Referenz zu PrintStream.println()
33
Constant Pool
Resolution
Reinhard Stumptner
Beispiel: Salutation- Applikation
private static int choice=(int)(Math.random()*2.99);
<clinit>():
0 invokestatic #13 <Method double random()>
java.lang.Math laden und binden
direkte Referenz eintragen
3 ldc2_w #14 <Double 2.99>
Wert 2.99
6 dmul
// Multiplikation
7 d2i// Konvertierung: double  int
8 putstatic #10 <Field int choice>
choice direkt referenzieren
11 return
34
Constant Pool
Resolution
Reinhard Stumptner
Beispiel: Salutation- Applikation
main():
0 ldc #2 <String “Hello, world!“>
2 astore_1
// speichert Referenz in 1. lokalen Variable
// s = hello;
3 getstatic #10 <Field int choice>
6 iconst_1
// push 1
7 if_icompne 16
// if (choice == 1) (choice sei hier =2)
10 ldc #1 <String “Greetings, planet!“>
12 astore_1
// s = greeting;
13 goto 26
16 getstatic #10 <Field int choice>
19 iconst_2
// push 2
20 if_icompne 26
// if (choice == 2)
35
Constant Pool
Resolution
Reinhard Stumptner
Beispiel: Salutation- Applikation
main():
23 ldc #3 <String “Salutations, orb!“>
25 astore_1
// s = salutation;
26 getstatic #11 <Field java.io.Printstream out>
29 aload_1
// push s für System.out.println(s);
30 invokevirtual #12 <Method void println(java.lang.String)
33 return
36
Constant Pool
Resolution
Reinhard Stumptner
Beispiel: Salutation- Applikation
Auflösen der symbolischen Referenzen:




37
ldc #2 <String “Hello, world!“>
– CONSTANT_String_info
– String Objekt “Hello, world!“ wird erzeugt, Referenz vermerken
– ldc  ldc_quick
getstatic #10 <Field int choice>
– Eintrag #10 wurde bei <clinit>() aufgelöst, getstatic  getstatic_quick
getstatic #10 <Field int choice>
– bereits aufgelöst, getstatic  getstatic_quick
ldc #3 <String “Salutations, orb!“>
– CONSTANT_String_info
– String Objekt erzeugen, Referenz bei Eintrag #3 vermerken
– ldc  ldc_quick
Constant Pool
Resolution
Reinhard Stumptner
Beispiel: Salutation- Applikation
Auflösen der symbolischen Referenzen:


38
getstatic #11 <Field java.io.Printstream out>
– CONSTANT_Fieldref_info
– java.lang.System laden und binden
– Prüfung auf Vorhandensein eines statischen Feldes out
– direkte Referenz zum Feld wird installiert, getstatic  getstatic_quick
invokevirtual #12 <Method void println(java.lang.String)>
– CONSTANT_Methodref_info
– java.io.PrintStream laden und binden
– Prüfung: Methode public, Rückgabe: void Parameter: String
– invokevirtual  invokevirtual_quick
Constant Pool
Resolution
Reinhard Stumptner
Eigene Lader
public class Base {
public Base b;
public Base() {
b = null;
System.out.println("\tBase Konstruktor");
}
public void print() {System.out.println("\tPrint Base");}
}
public class Derived extends Base {
public Derived() {
System.out.println("\tDerived Konstruktor");
}
}
39
Reinhard Stumptner
Eigene Lader
40
class MyLoader extends ClassLoader {
public Class findClass(String name) throws
ClassNotFoundException {
Class
newClass=searchLoadedType(name);
if (newClass==null){
byte[] classData = loadClassData(name);
newClass=defineClass(name, classData, 0,
classData.length);
}
return newClass;
}
private byte[] loadClassData(String name) throws
ClassNotFoundException {
File source=new File(name+".class");
BufferedInputStream in=…
byte[] b=new byte[in.available()];
in.read(b, 0, in.available());
return b;
}
Reinhard Stumptner
Eigene Lader
Verwendung eines benutzerdefinierten Laders:
MyLoader l=new MyLoader();
Class c1=l.loadClass("Derived");
c1.getClassLoader();
// Lader eines Typs kann
// abgerufen werden
java.lang.reflect.Method m;
m=c1.getMethod("print", null);
Object o=c1.newInstance();
m.invoke(o,null);
// Ausführen der Methode
// print() des erzeugten
// Objekts
41
Reinhard Stumptner
Eigene Lader
class MyDecryptLoader extends ClassLoader {
public Class findClass(String name) throws
ClassNotFoundException{
classData = loadClassData(name,key);
…
}
public byte[] loadClassData(String name, byte key){
byte[] b=null;
in.read(b, 0, in.available());
for (int i=0; i<b.length; i++) b[i]=(byte)(b[i] ^ key);
return b;
}
}
42
Reinhard Stumptner
Eigene Lader
public class CompilingClassLoader extends ClassLoader {
private boolean compile(String javaFile) throws IOException {
Process p = runtime.getRuntime().exec ("javac
"+javaFile);
p.waitFor();
return p.exitValue() == 0;
}
public Class loadClass(String name, boolean resolve) throws
ClassNotFoundException {
Class c = null;
if (!compile(name+".java")
throw new ClassNotFoundException();
…
c = defineClass(name, raw, 0, raw.length);
resolveClass(c);
}
43
Reinhard Stumptner
Herunterladen