1 / 43

Seminar Softwareentwicklung

Seminar Softwareentwicklung. Dynamisches Laden und Binden in Java. Dynamisches Laden und Binden in Java. Der Lebenszyklus eines Typs Der Lebenszyklus eines Objekts Dynamisches Binden Eigene Lader. Der Lebenszyklus eines Typs. Class-File laden. Drei Hauptaktivitäten:

shaina
Download Presentation

Seminar Softwareentwicklung

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Seminar Softwareentwicklung Dynamisches Laden und Binden in Java Reinhard Stumptner

  2. Dynamisches Laden und Binden in Java • Der Lebenszyklus eines Typs • Der Lebenszyklus eines Objekts • Dynamisches Binden • Eigene Lader Reinhard Stumptner

  3. Der Lebenszyklus eines Typs Reinhard Stumptner

  4. 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 Reinhard Stumptner

  5. 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 Reinhard Stumptner

  6. Vorbereiten des Typs • Für die Klassenvariablen wird Speicher reserviert und mit „0“ initialisiert • Anlegen zusätzlicher Datenstrukturen (Methodentabelle) Reinhard Stumptner

  7. Constant Pool auflösen Reinhard Stumptner

  8. 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 Reinhard Stumptner

  9. Initialisieren des Typs • Aktive vs. Passive Verwendung class A { static int x=10*Math.random(); static {System.out.println(“init A”);} } class Bextends 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 Reinhard Stumptner

  10. Der Lebenszyklus eines Objekts • Das Erzeugen einer Instanz stellt den Beginn des Lebenszyklus eines Objekts dar, Garbage Collection (bzw. finalize()) dessen Ende Reinhard Stumptner

  11. 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 Reinhard Stumptner

  12. 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) Reinhard Stumptner

  13. 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; } } Reinhard Stumptner

  14. 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 Reinhard Stumptner

  15. Freigeben eines Typs • Typen werden, wenn sie nicht mehr benötigt werden, freigegeben, d.h. wenn sie nicht erreichbar sind Reinhard Stumptner

  16. Dynamisches Binden – The Linking Model • Auflösen symbolischer Referenzen • Dynamische Erweiterung • Parent-Delegation Model • Constant Pool Resolution Reinhard Stumptner

  17. 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 Reinhard Stumptner

  18. 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; Reinhard Stumptner

  19. 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 Reinhard Stumptner

  20. 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 Reinhard Stumptner

  21. Resolution von Klassen und Interfaces Auflösen einer symbolischen Referenz auf eine Klasse: • 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 • Zugriffsrechte werden überprüft Verwendeter Lader: der, mit dem referenzierende Klasse geladen wurde Reinhard Stumptner

  22. 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 Reinhard Stumptner

  23. 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 Reinhard Stumptner

  24. 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;} } A- Instanz Reinhard Stumptner

  25. Resolution von Feldern und Methoden Methodentabelle von A: Typinformation von Object Typinformation von A Reinhard Stumptner

  26. 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 Reinhard Stumptner

  27. 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 Reinhard Stumptner

  28. 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. Reinhard Stumptner

  29. 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 Reinhard Stumptner

  30. Beispiel: Salutation- Applikation Symbolische Referenz zu “Hello, world!“ Reinhard Stumptner

  31. Beispiel: Salutation- Applikation Symbolische Referenzen von Salutation zu Math.random() Reinhard Stumptner

  32. Beispiel: Salutation- Applikation Symbolische Referenz zu System.out Reinhard Stumptner

  33. Beispiel: Salutation- Applikation Symbolische Referenz zu PrintStream.println() Reinhard Stumptner

  34. Beispiel: Salutation- Applikation private static int choice=(int)(Math.random()*2.99); <clinit>(): 0 invokestatic #13 <Method double random()> java.lang.Mathladen 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 Reinhard Stumptner

  35. 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) Reinhard Stumptner

  36. 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 Reinhard Stumptner

  37. 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 Reinhard Stumptner

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

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

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

  41. 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 Reinhard Stumptner

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

  43. 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); } Reinhard Stumptner

More Related