4 Stimmen

Java mit JAD dekompilieren - Einschränkungen

Ich versuche, ein paar JAR-Dateien mithilfe von JAD in Java zu dekompilieren (ich habe es auch mit JD-GUI versucht, jedoch mit noch weniger Glück), aber ich erhalte ziemlich viele Fehler. Ein Typ (einfach zu beheben) scheint mit internen Klassen zusammenzuhängen, aber ich fand auch diesen Code-Abschnitt:

static int[] $SWITCH_TABLE$atp$com$OrderType()
{
    $SWITCH_TABLE$atp$com$OrderType;
    if($SWITCH_TABLE$atp$com$OrderType == null) goto _L2; else goto _L1
_L1:
    return;
_L2:
    JVM INSTR pop ;
    int ai[] = new int[OrderType.values().length];
    try
    {
        ai[OrderType.LIMIT.ordinal()] = 2;
    }
    catch(NoSuchFieldError _ex) { }
    try
    {
        ai[OrderType.MARKET.ordinal()] = 1;
    }
    catch(NoSuchFieldError _ex) { }
    try
    {
        ai[OrderType.STOP.ordinal()] = 3;
    }
    catch(NoSuchFieldError _ex) { }
    try
    {
        ai[OrderType.TAKE.ordinal()] = 4;
    }
    catch(NoSuchFieldError _ex) { }
    return $SWITCH_TABLE$atp$com$OrderType = ai;
}

der wie folgt verwendet wird:

switch($SWITCH_TABLE$atp$com$OrderType()[co.getOrderType().ordinal()])
        {
        case 1: // '\001'
            order = new Order(userID, null, co.getOrderType(), co.getOrderSide(), co.getOrderID(), co.getOrderSecurity(), co.getOrderQuantity(), broker);
            break;

        case 2: // '\002'
            order = new Order(userID, null, co.getOrderType(), co.getOrderSide(), co.getOrderPrice(), co.getOrderID(), co.getOrderSecurity(), co.getOrderQuantity(), broker);
            break;

        case 3: // '\003'
            order = new Order(userID, null, co.getOrderType(), co.getOrderSide(), co.getOrderPrice(), co.getOrderID(), co.getOrderSecurity(), co.getOrderQuantity(), broker);
            break;
        }

Irgendeine Idee, was dieser Konstrukt ursprünglich hätte sein können?

7voto

kan Punkte 27175

Ich denke, es handelt sich um tableswitch für ein Enum. Es übersetzt den beliebigen Enum-Ordinalwert in die Zahl 0..n, was die Leistung der switch-Anweisung verbessert.

UPDATE Gerade verstanden! Das Problem ist - der Code, der das Enum verwendet, könnte separat vom Enum selbst kompiliert werden. Daher kennt er zur Kompilierungszeit nicht die ordinalen Werte, und kann daher keine ordnungsgemäße tableswitch-Anweisung konstruieren. Deshalb führt er die lazy SWITCH_TABLE-Struktur ein, um derzeit verfügbare ordinale Werte den örtlichen tableswitch-Int-Nummern zuzuordnen.

5voto

G_H Punkte 11428

Mir scheint das wie eine switch-Anweisung auf einem Enum zu sein. Schau dir die Enum-Klasse an, die Enums implizit erweitern. Sie verfügt über die ordinal-Methode, die für das Umschalten verwendet wird. Wahrscheinlich gibt es ein OrderType Enum mit den Konstanten LIMIT, MARKET, STOP und TAKE.

EDIT: Eigentlich wäre es schön, noch einige Informationen zu haben. Es werden einige Tricks und Kniffe für Sachen wie Enums verwendet. Eine Enum-Konstante erhält hinter den Kulissen eine Ordnungszahl. Diese Ordnungszahl wird tatsächlich in einer Vielzahl von Konstrukten verwendet. Wenn über eine Enum-Instanz umgeschaltet wird, erstellt der Compiler tatsächlich einen Schalter über einen int (eine bekannte Konstruktion, die schon seit einiger Zeit existiert) mit der Ordnungszahl als Eingabe.

Was in deinen beiden Codeblöcken passiert, ist folgendes: Der erste richtet eine "Tabelle" (eigentlich nur ein Array) für die Enum-Ordnungszahlen ein, wenn dies noch nicht geschehen ist. Es erfolgt eine Nullüberprüfung. Wenn die Tabelle null ist, springt es zum Label _L2, um die Initialisierung durchzuführen. Andernfalls springt es zum Label _L1, das einfach zurückgibt. Der zweite Codeblock (die eigentliche switch-Anweisung) führt einen Schalter über ein int aus. Das int wird aus der Tabelle erhalten, indem das Element am Index abgerufen wird, der der Ordnungszahl der Enum-Konstanten entspricht.

Es scheint ein bisschen seltsam zu sein, aber das bildet eine Art Indirektion zwischen den Enum-Ordnungszahlen und den intern verwendeten Werten des Schalters.

Der Grund, warum das alles so low-level aussieht, anstatt einfach einen Schalter auf einem Enum zu sehen, liegt darin, dass Enums in JDK 1.5 eingeführt wurden, JAD jedoch schon seit einiger Zeit nicht mehr gewartet wird und nur die Dekompilierung von Quellcode bis 1.4 unterstützt. Da Enums jedoch unter Verwendung von in 1.4 verfügbaren Konstrukten implementiert wurden, funktioniert die Dekompilierung tatsächlich, aber JAD hat kein Wissen über Enums und unternimmt daher keinen Versuch, dies auf eine lesbarere Weise darzustellen.

Hier ist, wie dieser zweite Codeblock wahrscheinlich aussah:

switch(co.getOrderType()) { //co.getOrderType() gibt den OrderType einer Variable zurück
    case MARKET : order = new Order(userID, null, co.getOrderType(), co.getOrderSide(), co.getOrderID(), co.getOrderSecurity(), co.getOrderQuantity(), broker);
                  break;
    case LIMIT : order = new Order(userID, null, co.getOrderType(), co.getOrderSide(), co.getOrderPrice(), co.getOrderID(), co.getOrderSecurity(), co.getOrderQuantity(), broker);
                 break;
    case STOP : order = new Order(userID, null, co.getOrderType(), co.getOrderSide(), co.getOrderPrice(), co.getOrderID(), co.getOrderSecurity(), co.getOrderQuantity(), broker);
                break;
}

0voto

Jeshurun Punkte 22314

Beim Verwenden der getDeclaredFields()-Methode der Reflektions-API auf Android wird, wenn der zu introspektierende Typ einen Enum-Switch enthält, in dem das Enum in einer anderen Klasse deklariert ist, eines der zurückgegebenen Felder die lazy SWITCH_TABLE-Struktur sein, die etwas ähnliches wie $SWITCH_TABLE$com$company$package$Klassenname$Enumname genannt wird.

Ich habe Reflektion verwendet, um automatisch Felder einer Klasse auf ContentValues abzubilden, bevor sie in der SQLite-Datenbank gespeichert werden, und habe gerade einen halben Tag damit verbracht, herauszufinden, warum das Array, das die Spaltennamen enthält, immer um eins daneben lag.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X