Angenommen, wir haben folgendes Classfile:
class apple { public int peanut(int a,int b) { return a+b+77; } }
Dies entspricht auf Bytecodeebene: (disassembliert durch javap)
Compiled from apple.java class apple extends java.lang.Object { public int peanut(int, int); apple(); } Method int peanut(int, int) 0 iload_1 1 iload_2 2 iadd 3 bipush 77 5 iadd 6 ireturn Method apple() 0 aload_0 1 invokespecial #3 <Method java.lang.Object()> 4 return
Ein minimales Formatfile zur Anzeige aller Methoden in apple.class würde folgendermassen aussehen:
********************************** method_head "Method $name\n"
Dieses erzeugt als Ausgabe:
Method peanut Method <init>
Hier sieht man zwei Methoden, obwohl nur eine definiert worden ist. Dies liegt daran dass der Compiler immer eine zusätzliche -Methode definiert, falls keine definiert worden ist. ( heissen alle Konstruktoren in java)
Wollen wir jetzt noch die eigentlichen Bytecodes disassemblieren, müssen wir entsprechende für jeden Befehlsnamen einführen.
Unser Formatfile sieht dann folgendermassen aus:
********************************** method_head "Method $name" op "\n\t" method_tail "\nEnd\n" aload_0 "aload 0" iload_1 "iload 1" iload_2 "iload 2" iadd "iadd" bipush "bipush $arg[0]" ireturn "ireturn" return "return" invokespecial "invokespecial <$arg[0]>"
Nun erhalten wir als Ausgabe:
Method peanut iload 1 iload 2 iadd bipush <77> iadd ireturn End Method <init> aload 0 invokespecial <3> return End
Hier sieht man schon den ersten ,,Profit'' unter Benutzung von : Durch die freie Namensgebung der zu disassemblierenden Opcodes köennen wir z.B. die (im Opcode unterschiedlichen) Befehle aload x,aload_0,aload_1,aload_2,aload_3 in ein generelles Format überführen. Dies ist insbesondere dann praktisch, wenn Java Bytecode in ein Format übersetzt werden soll, in dem nur ein Subset aller Befehle zur Verfügung steht, so dass Gruppen von Befehlen zu einer Einheit zusammengefasst oder Befehle durch andere Befehle emuliert werden sollen.
Eine Gefahr bei der Definition von Formatfiles liegt darin, dass Opcodes ,,verschluckt'' werden können, da für sie kein entsprechendes existiert. Eine einfache Möglichkeit in der Klasse vorkommende aber im Formatfile nicht definierte Opcodes zumindest als Fehler in der Ausgabe zu erhalten besteht darin, durch Einbindung von (wie alle bei Jissa mitgelieferten Formatfiles im etc-Directory zu finden) jeden Opcode vor Definition der ,,eigenen'' Opcodes mit einer Fehlermeldung als Ausgabe zu versehen, und dann die Opcodes, die im Formatfile vorkommen wieder mit der richtigen Ausgabe zu überschreiben. Dies klingt komplizierter als es ist. Unser Formatfile würde nun folgendermassen aussehen:
********************************** include error.inc method_head "Method $name" op "\n\t" method_tail "\nEnd\n" aload_0 "aload 0" iload_1 "iload 1" iload_2 "iload 2" iadd "iadd" bipush "bipush <$arg[0]>" ireturn "ireturn" return "return" invokespecial "invokespecial <$arg[0]>"
Dies ist im übrigen eine schöne Demonstration für die in den Formatfiles auch möglichen
Ein Ausschnitt aus errorinc:
. . pop2 "Opcode [58] not supported! (pop2)" dup "Opcode [59] not supported! (dup)" dup_x1 "Opcode [5a] not supported! (dup_x1)" dup_x2 "Opcode [5b] not supported! (dup_x2)" dup2 "Opcode [5c] not supported! (dup2)" dup2_x1 "Opcode [5d] not supported! (dup2_x1)" dup2_x2 "Opcode [5e] not supported! (dup2_x2)" swap "Opcode [5f] not supported! (swap)" . .
Würden wir jetzt unser appleclass-File um einen illegalen Opcode ergänzen, wie z.b. :
class apple { public int peanut(int a,int b) { return a*b+77; } }
So würden wir als Ausgabe erhalten:
Method peanut iload 1 iload 2 Opcode [68] not supported! (imul) bipush <77> iadd ireturn End Method <init> aload 0 invokespecial <3> return End
Eine Disassemblierung von apple.class mit dem bei jissa ,,mitgelieferten'' Classfile readable.fmt", welches im wesentlichen obige Definitionen noch erweitert sowie auch die anderen in java verfügbaren Opcodes einführt, sieht übrigens folgendermassen aus:
Filename apple.class Java Version 45.3 Class apple Superclass java/lang/Object 0 Interfaces 0 Fields 2 methods public function peanut (int,int) returns int iload_1 iload_2 iadd bipush 77 iadd ireturn function <init> () returns void aload_0 invokespecial [Methodref]java/lang/Object/<init> return (* Source: applet.java *)