next up previous contents
Nächste Seite: Implementierung Aufwärts: Benutzung Vorherige Seite: Includefiles   Inhalt

Beispiel

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 \(<init>\)-Methode definiert, falls keine definiert worden ist. (\(<init>\) heissen alle Konstruktoren in java)

Wollen wir jetzt noch die eigentlichen Bytecodes disassemblieren, müssen wir entsprechende \(contexttags\) 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 \(jissa\): 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 \(aload\) \(x\) ü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 \(minimalen\) Formatfiles liegt darin, dass Opcodes ,,verschluckt'' werden können, da für sie kein entsprechendes \(contexttag\) 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 \(error.inc\) (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 \(includefiles\)

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. \(imul\):

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 *)


next up previous contents
Nächste Seite: Implementierung Aufwärts: Benutzung Vorherige Seite: Includefiles   Inhalt
Matthias Kramm 2000-11-22