Projektgruppe “Verteilung von parallelen Java-Anwendungen” JV • Struktur von Klassendateien • Befehlssatz der JVM • Übersetzung grundlegender Java-Konstrukte • Wichtige Java-Konstrukte mit komplexerer Umsetzung M Java-Bytecode: Der Blick unter die Haube Michael Thies, 29.10.2001 JV M Übersetzen und Ausführen von Java-Programmen 1 Laufzeit Benutzer-Eingaben Bildschirm-Ausgaben Java Laufzeitumgebung Quelltext Ausführung CodeErzeugung ClassLoader Linker Java Compiler BytecodeErzeugung 0110 11001110 01110001 11001111 01011000 binäre Klassendatei 0110 11001110 01110001 11001111 01011000 weitere Dateien jar-Datei JV M Struktur einer Java-Klasse: Quelltext 2 package de.upb.example; public abstract class NamedDemo extends AbstractDemo implements Runable { Angaben zur Klasse protected String name; private static int count = 0; public static final int NO_DEMO = -1; Definition von Klassen-/ Instanzvariablen public String getName() { return name; } public void run() { doDemo(); } static int getCount() { return count; } public NamedDemo(String n) { name = n; } protected abstract void doDemo(); } Definition von Methoden, Konstruktoren JV M Struktur einer Java-Klasse: binäre Klassendatei 3 NamedDemo.class Kopf Kennung: 0xCAFEBABE Version: 45.3 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 Methoden-Definitionen name getName count getCount NO_DEMO run <init> doDemo JV M 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 ? Daten zugehörige ? Daten Daten Feld-Definition Feld-Definition Methoden-Definition Methoden-Definition Liste von Attributen standardisierte Attribute: • Pflicht-Attribute – Bytecode für Methoden 'Code' – Werte für Konstanten 'ConstantValue' • optionale Attribute – Informationen für Debugger 'LineNumberTable', 'SourceFile' JV M 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) JV M Typangaben in Klassendateien 6 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 in der Klassendatei Object Ljava/lang/Object; java.lang.String Ljava/lang/String; de.upb.example.NamedDemo Lde/upb/example/NamedDemo; 3. Anzahl Dimensionen und Elementtyp für Array-Typen • jede Dimension durch Präfix [ repräsentiert in Java in der Klassendatei float[][] [[F String[] [Ljava/lang/String; 7 JV M Definition von Methoden 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 Attribut Name: getName Name: 'Code' Signatur: () → void Länge: n1 Eigenschaften: public, nicht static Inhalt: Bytecode Methoden-Definition Methoden-Definition Name: doDemo Signatur: () → void Eigenschaften: protected, nicht static, abstract Attribut Name: <init> Name: 'Code' Signatur: (String) → void Länge: n2 Eigenschaften: public, nicht static Inhalt: Bytecode Konstruktor JV M 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 JVM: Methodenname und Textdarstellung der Signaturen müssen in Ober- und Unterklasse gleich sein JV M Architektur und Befehlssatz der Java Virtual Machine (JVM) 9 JVM ThreadScheduler Java-Bytecode • Befehlssatz eines abstrakten Prozessors • stark auf Java zugeschnitten • 0-Adressmaschine (Kellerarchitektur) mit zusätzlichen Registern ClassLoader Abstrakter Prozessor Linker Finalizer Garbage Collector 0 1 2 3 • 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 Objektreferenz fadd dadd — fmul dmul — Operation Addition iadd Multiplikation imul Ergebnisireturn freturn dreturn rückgabe Vergleich if_icmp fcmp dcmp areturn if_acmp 10 JV M Java-Bytecode: Struktur des Befehlssatzes unterstützte Datentypen: • • • • int, float, Objektreferenzen long, double eingeschränkt: byte, short, char gar nicht: boolean Größe: 1 JVM-Wort Größe: 2 JVM-Worte ↔ int 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 JV M Kellerarchitektur: Arithmetik mit der JVM 11 Bytecode: iconst 3 iconst 4 iadd iconst 6 imul 4 3 iadd 6 7 imul 7 Ausdrücke in Postfix-Form: (3 + 4) ∗ 6 → 3 4 + iconst 3 iconst 4 iadd 42 6 ∗ iconst 6 imul 12 JV M Speichermodell der JVM Methode m Bytecode hat Zugriff auf: global lokal für Methode (mit fester Größe) dup, Arithmetik putstatic Objekt Klasse Tstore getstatic Tload putfield Objekt Objekt getfield Objektspeicher (heap) Operandenkeller 0 1 2 3 4 5 6 7 Register (lokale Variablen) JV M Übersetzung: Zugriffe auf Klassen-/Instanzvariablen 13 Lesen Klassenvariable int i = NamedDemo.count; getstatic <NamedDemo.count> istore 3 Reg. 3 ist i Instanzvariable Schreiben NamedDemo.count = 0; iconst 0 putstatic <NamedDemo.count> int i = this.age; this.age = 18; aload 0 aload 0 iconst 18 putfield <Person.age> getfield <Person.age> istore 3 Reg. 3 ist i JV M Kontrollfluß: Sprünge und Distanzen 14 Fallunterscheidung if (x > y) this.max = x; else this.max = y; 0: 1: 2: 5: 6: 7: 10: 13: 14: 15: 18: iload 2 Reg. 2 ist x iload 3 Reg. 3 ist y if_icmple +11 aload 0 iload 2 putfield <Cond.max> goto +8 aload 0 iload 3 putfield <Cond.max> … Byte-Offsets im Bytecode abweisende Schleife int res = 1; int i = 0; while (i < 7) { res = 5 * res; i = i + 1; } 0: 1: 2: 3: 4: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 18: 21: iconst 1 istore 2 Reg. 2 ist res iconst 0 istore 3 Reg. 3 ist i goto +11 iconst 5 iload 2 imul istore 2 iload 3 iconst 1 iadd istore 3 iload 3 iconst 7 if_icmplt -11 … JV M Übersetzung von Methodenaufrufen 15 Klassenmethode int v, w = 9; v = Math.max(-w, 0); 0: 2: 3: 4: 5: 6: 9: 10: iconst 9 istore 3 Reg. 3 ist w iload 3 ineg iconst 0 invokestatic <Math.max> istore 2 Reg. 2 ist v … Instanzmethode Graphics g; g.drawString(20, 30, "Hallo"); 0: 1: 3: 5: 7: 10: aload 4 Reg. 4 ist g iconst 20 iconst 30 ldc "Hallo" invokevirtual <Graphics.drawString> … 16 JV M Ausführung von Methodenaufrufen Treturn invokexxx 2 Parameter Schachtel aufgerufene Methode Laufzeitkeller Schachtel Aufrufer 0 1 2 3 Parameterübergabe 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 0 1 2 3 Ergebnisrückgabe 17 JV M Bindung von Methodenaufrufen 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: … JVM wählt Implementierung von repaint() gemäß Typ der Objektreferenz auf dem Keller aus. Component • repaint() TextArea Label • repaint() • repaint() JV M Java-Bytecode: Befehle kompakt codiert 18 Beispiel: int-Konstanten kellern Wertebereich Befehl Format Länge –1, …, 5 iconst_n 0x02, …, 0x08 1 -128, …, 127 bipush n 0x10 n 2 -32768, …, 32767 sipush n 0x11 n1 n2 3 Sonstige ldc idx, ldc_w idx 0x12 idx, 0x13 idx1 idx2 2 + 4, 3 + 4 Beispiel: Objektreferenz im Register kellern Register-Nr. Befehl Format Länge 0, …, 3 aload_n 0x2a, …, 0x2d 1 4, …, 255 aload n 0x19 n 2 256, …, 65535 wide aload n 0xc4 0x19 n1 n2 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 19 JV M Klassendateien: kompakt dank ConstantPool? ConstantPool Quelltext Index Eintragstyp Daten 1 2 3 4 5 6 7 8 Hello! Index 1 java/lang/String Index 3 length ()I Indizes 5, 6 Indizes 4, 7 UTF8 String UTF8 Class UTF8 UTF8 NameAndType Methodref "Hello!".length() Bytecode ldc #2 invokevirtual #8 String Methodref "Hello!" Einträge im ConstantPool Class "java/lang/String" Typ des Empfängers NameAndType "length" "()I" Methodenname Signatur • ConstantPool speichert identische Einträge nur einmal • macht im Mittel 60% der Größe einer Klassendatei aus