Post on 24-Jan-2016
description
Reinhard Stumptner
Seminar Softwareentwicklung
Dynamisches Laden und Binden in Java
Reinhard Stumptner2
Dynamisches Laden und Binden in Java
Der Lebenszyklus eines Typs Der Lebenszyklus eines Objekts Dynamisches Binden Eigene Lader
Der Lebenszyklus eines Typs
Reinhard Stumptner3
Der Lebenszyklus eines Typs
Der Lebenszyklus eines Typs
Reinhard Stumptner4
Class-File laden
Drei Hauptaktivitäten:– 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 Stumptner5
Class-File verifizieren
Entspricht es der Semantik von Java? Prüfungen in der Verifikationsphase:
– 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 Stumptner6
Vorbereiten des Typs
Für die Klassenvariablen wird Speicher reserviert und mit „0“ initialisiert
Anlegen zusätzlicher Datenstrukturen (Methodentabelle)
Der Lebenszyklus eines Typs
Reinhard Stumptner7
Constant Pool auflösen
Der Lebenszyklus eines Typs
Reinhard Stumptner8
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:
– 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 Stumptner9
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: init C init A finished
Der Lebenszyklus eines Objekts
Reinhard Stumptner10
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
new A()
Typinformation von A
Der Lebenszyklus eines Objekts
Reinhard Stumptner11
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 obj2 = obj.clone();
– Deserialisieren eines Objekts mit getObject(), enthalten in java.io.ObjectInputStream
Der Lebenszyklus eines Objekts
Reinhard Stumptner12
Instanzieren einer Klasse
Reservieren von Speicher am Heap– 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 Stumptner13
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;
}}
Der Lebenszyklus eines Objekts
Reinhard Stumptner14
Freigeben eines Objekts
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 Stumptner15
Freigeben eines Typs
Typen werden, wenn sie nicht mehr benötigt werden, freigegeben, d.h. wenn sie nicht erreichbar sind
Reinhard Stumptner16
Dynamisches Binden – The Linking Model
Auflösen symbolischer Referenzen Dynamische Erweiterung Parent-Delegation Model Constant Pool Resolution
The Linking Model Reinhard Stumptner17
Auflösen symbolischer Referenzen
.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 Stumptner18
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)
public static Class forName (String className, boolean initialize, ClassLoader loader) throws ClassNotFoundException;
– java.lang.ClassLoader: (Binden offen) protected Class loadClass (String name, boolean resolve) throws ClassNotFoundException;
The Linking Model Reinhard Stumptner19
Parent-Delegation Model
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
Constant Pool Resolution Reinhard Stumptner20
Constant Pool Resolution
Der Constant Pool ist mit Symboltabellen vergleichbar
Struktur eines Eintrags:
CONSTANT_Class_Eintrag {byte Tag(=7);short Namensindex;
}Typen der Einträge im Konstantenpool
Constant Pool Resolution Reinhard Stumptner21
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
2. C wird initialisiert3. Zugriffsrechte werden überprüftVerwendeter Lader: der, mit dem referenzierende
Klasse geladen wurde
Constant Pool Resolution Reinhard Stumptner22
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“) Z….boolean, B….byte, I….int, …
– Referenztyp diesen laden, binden Von Bootstrap geladen
Constant Pool Resolution Reinhard Stumptner23
Resolution von Feldern und Methoden
CONSTANT_Fieldref: Klassen- oder Instanzvariable
CONSTANT_Methodref: Methode einer Klasse
Klassenvariablen, statische Methoden werden durch Referenz auf Typinformationen aufgelöst
Constant Pool Resolution Reinhard Stumptner24
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;}}
0 Zeiger in Method Area
1 x
2 s
A- Instanz
Constant Pool Resolution Reinhard Stumptner25
Resolution von Feldern und Methoden
Methodentabelle von A:
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()
Typinformation von Object
Typinformation von A
Constant Pool Resolution Reinhard Stumptner26
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
Constant Pool Resolution Reinhard Stumptner27
Resolution von anderen Elementen im Constant Pool
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 Stumptner28
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.
Constant Pool Resolution Reinhard Stumptner29
Beispiel: Salutation- Applikation
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 Stumptner30
Beispiel: Salutation- Applikation
Symbolische Referenz zu “Hello, world!“
Constant Pool Resolution Reinhard Stumptner31
Beispiel: Salutation- Applikation
Symbolische Referenzen von Salutation zu Math.random()
Constant Pool Resolution Reinhard Stumptner32
Beispiel: Salutation- Applikation
Symbolische Referenz zu System.out
Constant Pool Resolution Reinhard Stumptner33
Beispiel: Salutation- Applikation
Symbolische Referenz zu PrintStream.println()
Constant Pool Resolution Reinhard Stumptner34
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 referenzieren11 return
Constant Pool Resolution Reinhard Stumptner35
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 2616 getstatic #10 <Field int choice>19 iconst_2 // push 220 if_icompne 26 // if (choice == 2)
Constant Pool Resolution Reinhard Stumptner36
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
Constant Pool Resolution Reinhard Stumptner37
Beispiel: Salutation- Applikation
Auflösen der symbolischen Referenzen:
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 Stumptner38
Beispiel: Salutation- Applikation
Auflösen der symbolischen Referenzen:
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
Reinhard Stumptner39
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"); }}
Reinhard Stumptner40
Eigene Lader
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 Stumptner41
Eigene Lader
Verwendung eines benutzerdefinierten Laders:
MyLoader l=new MyLoader(); Class c1=l.loadClass("Derived");
c1.getClassLoader(); // Lader eines Typs kann // abgerufen
werdenjava.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
Reinhard Stumptner42
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;
}}
Reinhard Stumptner43
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);
}