Eine Methodendefinition wird mit der Direktive Methodendefinition:
.method <methodmodifiers> <methodname><methoddescriptor>
<statements>
.end method Der Methodenkörper wird mit sogenannten Statements ausgefüllt, wobei Direktiven, Labels und die Instruktionen der virtuellen Java-Maschine als Statements gelten. Bestimmte Direktiven sind nur innerhalb des Methodenkörpers zulässig, die demnach auch als Methodendirekiven bezeichnet werden. Sie sollen im Anschluss näher erläutert werden. Methodendirektiven:
Die Methodendirektiven
Die Methodendirektiven .limit stack <integer> .limit locals <integer> Die beiden oberen Schranken des Stapels und des Arrays werden hinter den
jeweiligen Direktiven notiert, wobei für die Angabe
Beispiel: Klassendefinition mit leerem Klassenkörper Als Beispiel soll an dieser Stelle der folgende Java-Quelltext einer Klasse mit leerem Klassenkörper auf den zughörigen Jasmin-Quelltext abgebildet werden. /* EmptyClass.java */ public class EmptyClass { } Die Klassendatei, die mit der Compilierung von Listing 5.2. ; EmptyClass.j .bytecode 50.0 .class public EmptyClass .super java/lang/Object .method public <init>()V .limit stack 1 .limit locals 1 aload_0 invokespecial java/lang/Object/<init>()V return .end method Dabei wird deutlich, dass
Beispiel: Instanzmethode und Als zweites Beispiel soll eine Klasse in Jasmin-Assemblersprache erstellt
werden, die eine Instantzmethode und eine statische
/* BasicClass.java */ public class BasicClass { public void method1() { } public static void main(String[] args) { } } Das folgende Listing Listing 5.3. ; BasicClass.j .bytecode 50.0 .class public BasicClass .super java/lang/Object .method public <init>()V .limit stack 1 .limit locals 1 aload_0 invokespecial java/lang/Object/<init>()V return .end method .method public method1()V .limit stack 0 .limit locals 1 ; JVM-Instruktionen ; (stack- und locals-Begrenzung anpassen) return .end method .method public static main([Ljava/lang/String;)V .limit stack 0 .limit locals 1 ; JVM-Instruktionen ; (stack- und locals-Begrenzung anpassen) return .end method Die beiden Methoden
Innerhalb eines Java-Quelltextes werden Ausnahmen (Exceptions) mit der
bekannten .catch <classname> from <label> to <label> using <label> .catch <classname> from <offset> to <offset> using <offset> Direkt nach der Schlüsselbezeichnung /* CatchExample.java */ public class CatchExample { public static void main(String[] args) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } } Die Listing 5.4. ; CatchExample.j .bytecode 50.0 .class public CatchExample .super java/lang/Object .method public <init>()V .limit stack 1 .limit locals 1 aload_0 invokespecial java/lang/Object/<init>()V return .end method .method public static main([Ljava/lang/String;)V .limit stack 2 .limit locals 2 Label1: ldc2_w 5000 invokestatic java/lang/Thread/sleep(J)V Label2: goto Label4 Label3: astore_1 aload_1 invokevirtual java/lang/InterruptedException/printStackTrace()V Label4: return .catch java/lang/InterruptedException from Label1 to Label2 using Label3 .end method Im Jasmin-Listing wurden für die Verwendung von pc-Labels: 0: ldc2_w 5000 3: invokestatic java/lang/Thread/sleep(J)V 6: goto 14 9: astore_1 10: aload_1 11: invokevirtual java/lang/InterruptedException/printStackTrace()V 14: return .catch java/lang/InterruptedException from 0 to 6 using 9 Direktive .catch nutzt absolute Offsets: ldc2_w 5000 invokestatic java/lang/Thread/sleep(J)V goto Label4 astore_1 aload_1 invokevirtual java/lang/InterruptedException/printStackTrace()V Label4: return .catch java/lang/InterruptedException from 0 to 6 using 9
Ein möglicherweise auftretende Exception innerhalb einer Methode muss
entweder innerhalb eines Java-Quelltextes mit einer
/* ThrowsExample.java */ public class ThrowsExample { public static void main(String[] args) throws InterruptedException { Thread.sleep(5000); } } Die Weitergabe einer Exception kann im Jasmin-Quelltext mit der
Methodendirektive .throws <classname> Die Direktive verlangt die Angabe der Fehlerklasse. Zulässige Fehlerklassen
sind wie bei der Direktive Listing 5.5. ; ThrowsExample.j .bytecode 50.0 .class public ThrowsExample .super java/lang/Object .method public <init>()V .limit stack 1 .limit locals 1 aload_0 invokespecial java/lang/Object/<init>()V return .end method .method public static main([Ljava/lang/String;)V .limit stack 2 .limit locals 1 ldc2_w 5000 invokestatic java/lang/Thread/sleep(J)V return .throws java/lang/InterruptedException .end method
Mit Hilfe der Methodendirektive .line <integer> Nach dem Schlüsselwort Listing 5.6. 1 ; LineExample.j 2 3 .bytecode 50.0 4 .source LineExample.j 5 .class public LineExample 6 .super java/lang/Object 7 8 .method public <init>()V 9 .limit stack 1 10 .limit locals 1 11 .line 12 12 0: aload_0 13 1: invokespecial java/lang/Object/<init>()V 14 4: return 15 .end method 16 17 .method public static main([Ljava/lang/String;)V 18 .limit stack 2 19 .limit locals 2 20 .line 21 21 0: bipush 10 22 2: istore_1 23 .line 24 24 3: iload_1 25 4: iconst_1 26 5: iadd 27 6: istore_1 28 .line 29 29 7: return 30 .end method Im folgenden soll kurz darauf eingegangen werden, an welcher Stelle der
Klassendatei die Debugging-Informationen stehen.
Der Assemblerquelltext enthält vier Abbildung 5.1. Hexadezimale Darstellung der Klassendatei ca fe ba be 00 00 00 32 00 0f 0a 00 0e 00 07 01 .......2........ 0 00 0d 4c 69 6e 65 45 78 61 6d 70 6c 65 2e 6a 01 ..LineExample.j. 16 00 10 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 ..java/lang/Obje 32 63 74 01 00 0a 53 6f 75 72 63 65 46 69 6c 65 01 ct...SourceFile. 48 00 06 3c 69 6e 69 74 3e 01 00 04 6d 61 69 6e 0c ..<init>...main. 64 00 05 00 0d 01 00 04 43 6f 64 65 01 00 0b 4c 69 .......Code...Li 80 6e 65 45 78 61 6d 70 6c 65 01 00 0f 4c 69 6e 65 neExample...Line 96 4e 75 6d 62 65 72 54 61 62 6c 65 07 00 09 01 00 NumberTable..... 112 16 28 5b 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 .([Ljava/lang/St 128 72 69 6e 67 3b 29 56 01 00 03 28 29 56 07 00 03 ring;)V...()V... 144 00 21 00 0b 00 0e 00 00 00 00 00 02 00 01 00 05 .!.............. 160 00 0d 00 01 00 08 00 00 00 1d 00 01 00 01 00 00 ................ 176 00 05 2a b7 00 01 b1 00 00 00 01 00 0a 00 00 00 ..*............. 192 06 00 01 00 00 00 0c 00 09 00 06 00 0c 00 01 00 ................ 208 08 00 00 00 28 00 02 00 02 00 00 00 08 10 0a 3c ....(..........< 224 1b 04 60 3c b1 00 00 00 01 00 0a 00 00 00 0e 00 ..`<............ 240 03 00 00 00 15 00 03 00 18 00 07 00 1d 00 01 00 ................ 256 04 00 00 00 02 00 02 ....... 272 Die folgende Übersicht macht deutlich welche .line 12 --> Bytes 211 - 214 00 00 00 0c (Index: 0x0000, Zeile: 0x000c) .line 21 --> Bytes 257 - 260 00 00 00 15 (Index: 0x0000, Zeile: 0x0015) .line 24 --> Bytes 261 - 264 00 03 00 18 (Index: 0x0003, Zeile: 0x0018) .line 29 --> Bytes 265 - 268 00 07 00 1d (Index: 0x0007, Zeile: 0x001d) Diese Bytes können nun zusammen mit dem Namen der Quelldatei
(
Ebenso wie die Methodendirektive .var <varnumber> is <varname> <fielddescriptor> [signature <fieldsignature>] from <label> to <label> .var <varnumber> is <varname> <fielddescriptor> [signature <fieldsignature>] from <offset> to <offset> Als Ausgangspunkt für ein Beispiellisting zur /* VarExample.java */ import java.util.*; public class VarExample { public static void main(String[] args) { int i = 3; int j = 4; Vector<Integer> v = new Vector<Integer>(); v.add(new Integer(i)); } } Innerhalb der .limit locals 4 .var 0 is args [Ljava/lang/String; from ... to ... .var 1 is i I from ... to ... .var 2 is j I from ... to ... .var 3 is v Ljava/util/Vector; signature "Ljava/util/Vector<Ljava/lang/Integer;>;" from ... to ... Neben den drei lokalen Variablen Listing 5.7. ; VarExample.j .bytecode 50.0 .class public VarExample .super java/lang/Object .method public <init>()V .limit stack 1 .limit locals 1 .var 0 is this LVarExample; from Label0 to Label4 Label0: aload_0 invokespecial java/lang/Object/<init>()V Label4: 4: return .end method .method public static main([Ljava/lang/String;)V .limit stack 4 .limit locals 4 .var 0 is args [Ljava/lang/String; from Label0 to Label25 .var 1 is i I from Label2 to Label25 .var 2 is j I from Label4 to Label25 ; folgende .var-Direktive in einer einzigen Zeile anordnen .var 3 is v Ljava/util/Vector; signature "Ljava/util/Vector<Ljava/lang/Integer;>;" from Label12 to Label25 Label0: iconst_3 istore_1 Label2: iconst_4 istore_2 Label4: new java/util/Vector dup invokespecial java/util/Vector/<init>()V astore_3 Label12: aload_3 new java/lang/Integer dup iload_1 invokespecial java/lang/Integer/<init>(I)V invokevirtual java/util/Vector/add(Ljava/lang/Object;)Z pop Label25: return .end method Anmerkung: Soll die Klassendatei > javac -g VarExample.java |
|