Projektgruppe Verteilung von parallelen Java-Anwendungen Java-Bytecode: Der Blick unter die Haube Struktur von Klassendateien Befehlssatz der Übersetzung grundlegender Java-Konstrukte Wichtige Java-Konstrukte mit komplexerer Umsetzung Michael Thies, 29.10.2001
Übersetzen und Ausführen von Java-Programmen 1 Laufzeit Benutzer-Eingaben Bildschirm-Ausgaben Quelltext Java Laufzeitumgebung Java Compiler Bytecode- Erzeugung Ausführung ClassLoader Code- Erzeugung Linker 0110 11001110 01110001 11001111 01011000 binäre Klassendatei weitere Dateien jar-datei 0110 11001110 01110001 11001111 01011000
Struktur einer Java-Klasse: Quelltext 2 package de.upb.example; public abstract class NamedDemo extends AbstractDemo implements Runable { protected String name; } private static int count = 0; public static final int NO_DEMO = -1; public String getname() { return name; } public void run() { dodemo(); } static int getcount() { return count; } public NamedDemo(String n) { name = n; } protected abstract void dodemo(); Angaben zur Klasse Definition von Klassen-/ Instanzvariablen Definition von Methoden, Konstruktoren
Struktur einer Java-Klasse: binäre Klassendatei 3 Kopf Kennung: 0xCAFEBABE Version: 45.3 NamedDemo.class ConstantPool Tabelle mit Namen, externen Referenzen Klassen-Definition Name: de.upb.example.nameddemo Oberklasse: de.upb.example.abstractdemo Interfaces: java.lang.runable Eigenschaften: public, abstract Feld-Definitionen name count NO_DEMO Methoden-Definitionen getname getcount run <init> dodemo
Attribute: Bausteine der Information in Klassendateien 4 Klassendatei Kopf ConstantPool Klassen-Definition Attribute Name, Länge der Daten Name, Länge der Daten Name, Länge der Daten zugehörige zugehörige? zugehörige Daten? Daten? Daten Feld-Definition Feld-Definition Methoden-Definition Methoden-Definition standardisierte Attribute: Pflicht-Attribute Bytecode für Methoden 'Code' Werte für Konstanten 'ConstantValue' optionale Attribute Informationen für Debugger 'LineNumberTable', 'SourceFile' Liste von Attributen
Definition von Feldern (Klassen-/Instanzvariablen) 5 Feld-Definition Name des Feldes deklarierter Typ Eigenschaften: Sichtbarkeit Instanz- oder Klassenfeld Sonstige: final, transient, volatile Wert von Konstanten Beispiele: Feld-Definition Name: name Typ: String Eigenschaften: protected, nicht static Feld-Definition Name: count Typ: int Eigenschaften: private, static Feld-Definition Name: NO_DEMO Typ: int Eigenschaften: public, static, final Attribut Name: 'ConstantValue' Länge: 2 Inhalt: (int, -1)
Typangaben in Klassendateien kompakte Textdarstellung für alle Java-Typdeklarationen: 1. Großbuchstaben für Grundtypen in Java int double float long boolean in der Klassendatei I D F J Z 2. vollständige Klassennamen für Referenztypen eingeschlossen in L und ; ähnlich wie Pfadangaben unter UNIX mit / als Trennzeichen in Java Object java.lang.string de.upb.example.nameddemo in der Klassendatei Ljava/lang/Object; Ljava/lang/String; Lde/upb/example/NamedDemo; 6 3. Anzahl Dimensionen und Elementtyp für Array-Typen jede Dimension durch Präfix [ repräsentiert in Java float[][] String[] in der Klassendatei [[F [Ljava/lang/String;
Definition von Methoden 7 Methoden-Definition Name der Methode Signatur der Methode Eigenschaften: Sichtbarkeit Instanz- oder Klassenmethode Sonstige: final, abstract, native, synchronized ausgelöste, geprüfte Ausnahmen Attribut 'Exceptions' Implementierung der Methode Attribut 'Code' Beispiele: Methoden-Definition Name: getname Signatur: () void Eigenschaften: public, nicht static Attribut Name: 'Code' Länge: n 1 Inhalt: Bytecode Methoden-Definition Name: dodemo Signatur: () void Eigenschaften: protected, nicht static, abstract Methoden-Definition Name: <init> Signatur: (String) void Eigenschaften: public, nicht static Attribut Name: 'Code' Länge: n 2 Inhalt: Bytecode Konstruktor
Methoden-Signaturen als Erweiterung der Typangabe 8 kompakte Textdarstellung für Parametertypen und Ergebnistyp: '(' Parametertyp ')' Ergebnistyp Parametertyp, Ergebnistyp: wie bei Typangaben für Felder zusätzlich V für Ergebnistyp void Beispiele: Methodenkopf in Java String getname() void setname(string n) boolean find(double[] v, float f) Signatur in der Klassendatei ()Ljava/lang/String; (Ljava/lang/String;)V ([DF)Z Überschreiben von Methoden aus Sicht der : Methodenname und Textdarstellung der Signaturen müssen in Ober- und Unterklasse gleich sein
Architektur und Befehlssatz der Java Virtual Machine () 9 Java-Bytecode Befehlssatz eines abstrakten Prozessors stark auf Java zugeschnitten 0-Adressmaschine (Kellerarchitektur) mit zusätzlichen Registern 0 1 2 3 Class- Loader Linker Thread- Scheduler Abstrakter Prozessor Garbage Collector Finalizer Befehle sind typisiert (die meisten) keine Typinformation für Kellerelemente und Register Bytecode-Verifikation leitet Typinformation her und prüft Konsistenz Typ int float double Objekt- Operation referenz Addition iadd fadd dadd Multiplikation imul fmul dmul Ergebnisrückgabe ireturn freturn dreturn areturn Vergleich if_icmp fcmp dcmp if_acmp
Java-Bytecode: Struktur des Befehlssatzes 10 unterstützte Datentypen: int, float, Objektreferenzen long, double eingeschränkt: byte, short, char gar nicht: boolean int Größe: 1 -Wort Größe: 2 -Worte 202 verschiedene Bytecode-Befehle darunter viele spezielle Kurzformen (CISC-artig) Befehlsgruppen: Arithmetik Datentransport Konstanten laden Werte transportieren Sprungbefehle (bedingt/unbedingt) Zugriffe auf Felder Methodenaufruf und -rücksprung spezielle Unterstützung für Java Objekterzeugung Typtest und Typumwandlung Exceptions auslösen const 0 1 2 3 universeller abstrakter Prozessor Java-spezifischer abstrakter Prozessor
Kellerarchitektur: Arithmetik mit der 11 Bytecode: iconst 3 iconst 4 iadd iconst 6 imul 4 3 6 7 iadd imul 7 42 Ausdrücke in Postfix-Form: (3 + 4) 6 3 4 + 6 iconst 3 iconst 4 iadd iconst 6 imul
Speichermodell der 12 Methode m Bytecode hat Zugriff auf: global lokal für Methode (mit fester Größe) dup, Arithmetik 0 1 Objekt Klasse putstatic getstatic putfield Tstore Tload 2 3 4 5 Objekt Objekt getfield 6 7 Objektspeicher (heap) Operandenkeller Register (lokale Variablen)
Übersetzung: Zugriffe auf Klassen-/Instanzvariablen 13 Lesen int i = NamedDemo.count; getstatic <NamedDemo.count> istore 3 Reg. 3 ist i Schreiben NamedDemo.count = 0; iconst 0 putstatic <NamedDemo.count> Klassenvariable Instanzvariable int i = this.age; aload 0 getfield <Person.age> istore 3 Reg. 3 ist i this.age = 18; aload 0 iconst 18 putfield <Person.age>
Fallunterscheidung if (x > y) this.max = x; else this.max = y; Kontrollfluß: Sprünge und Distanzen abweisende Schleife int res = 1; int i = 0; while (i < 7) { res = 5 * res; i = i + 1; } 14 0: iload 2 Reg. 2 ist x 1: iload 3 Reg. 3 ist y 2: if_icmple +11 5: aload 0 6: iload 2 7: putfield <Cond.max> 10: goto +8 13: aload 0 14: iload 3 15: putfield <Cond.max> 18: Byte-Offsets im Bytecode 0: iconst 1 1: istore 2 Reg. 2 ist res 2: iconst 0 3: istore 3 Reg. 3 ist i 4: goto +11 7: iconst 5 8: iload 2 9: imul 10: istore 2 11: iload 3 12: iconst 1 13: iadd 14: istore 3 15: iload 3 16: iconst 7 18: if_icmplt -11 21:
Übersetzung von Methodenaufrufen 15 Klassenmethode int v, w = 9; v = Math.max(-w, 0); 0: iconst 9 2: istore 3 Reg. 3 ist w 3: iload 3 4: ineg 5: iconst 0 6: invokestatic <Math.max> 9: istore 2 Reg. 2 ist v 10: Instanzmethode Graphics g; g.drawstring(20, 30, "Hallo"); 0: aload 4 Reg. 4 ist g 1: iconst 20 3: iconst 30 5: ldc "Hallo" 7: invokevirtual <Graphics.drawString> 10:
Ausführung von Methodenaufrufen 16 invokexxx 2 Parameter Treturn Schachtel aufgerufene Methode Laufzeitkeller Schachtel Aufrufer 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 0 1 2 3 0 1 2 3 Parameterübergabe Ergebnisrückgabe
Bindung von Methodenaufrufen 17 Bytecode-Befehl Bindung Empfänger Beispiel-Situation (this) invokevirtual dynamisch (Klasse) ja Component c; c.repaint(); invokeinterface dynamisch (Interface) ja Enumeration elems; elems.nextelement(); invokestatic statisch nein Thread.sleep(1000); invokespecial statisch ja super.paint(g); Ausführung dynamischer Methodenbindung: 0: aload 3 1: invokevirtual <Component.repaint> 4: Component repaint() wählt Implementierung von repaint() gemäß Typ der Objektreferenz auf dem Keller aus. TextArea repaint() Label repaint()
Java-Bytecode: Befehle kompakt codiert 18 Beispiel: int-konstanten kellern Wertebereich 1,, 5-128,, 127-32768,, 32767 Sonstige Befehl iconst_n bipush n sipush n ldc idx, ldc_w idx Format 0x02,, 0x08 0x10 n 0x11 n 1 n 2 0x12 idx, 0x13 idx 1 idx 2 Länge 1 2 3 2 + 4, 3 + 4 Beispiel: Objektreferenz im Register kellern Register-Nr. 0,, 3 4,, 255 256,, 65535 Befehl aload_n aload n wide aload n Format 0x2a,, 0x2d 0x19 n 0xc4 0x19 n 1 n 2 Länge 1 2 4 Spezialbefehl für häufiges Idiom: lokale Variable inkrementieren/dekr. iload n iconst c iadd istore n iinc n, c im besten Fall: 3 statt 7 Bytes
Klassendateien: kompakt dank ConstantPool? 19 ConstantPool Index Eintragstyp Daten Quelltext "Hello!".length() 1 UTF8 Hello! 2 String Index 1 3 UTF8 java/lang/string 4 Class Index 3 5 UTF8 length 6 UTF8 ()I 7 NameAndType Indizes 5, 6 8 Methodref Indizes 4, 7 Bytecode ldc #2 invokevirtual #8 Methodref String "Hello!" Einträge im ConstantPool Class NameAndType "java/lang/string" "length" "()I" Typ des Empfängers Methodenname Signatur ConstantPool speichert identische Einträge nur einmal macht im Mittel 60% der Größe einer Klassendatei aus