Декомпиляция Java с JAD - ограничения - PullRequest
4 голосов
/ 24 октября 2011

Я пытаюсь декомпилировать пару jar-файлов, используя JAD в Java (я также пробовал JD-GUI с еще меньшей удачей), но я получаю довольно много ошибок. Один тип (легко исправить), кажется, для внутренних классов, но я также нашел этот фрагмент кода:

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;
}

, который используется следующим образом:

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;
        }

Есть идеи, какой изначально могла быть эта конструкция?

Ответы [ 3 ]

7 голосов
/ 24 октября 2011

Я думаю, что это табличный переключатель для перечисления. Он переводит произвольное порядковое значение enum в число 0..n, это позволяет повысить производительность оператора switch.

UPDATE Просто понял это! Проблема в том, что код, использующий перечисление, может быть скомпилирован отдельно от самого перечисления. Таким образом, он не знает во время компиляции порядковые значения, поэтому он не может создать правильную операцию переключения таблиц. Вот почему он вводит ленивую структуру SWITCH_TABLE, чтобы отобразить доступные в настоящий момент порядковые значения для локальных чисел переключателя табличного переключателя.

5 голосов
/ 24 октября 2011

Выглядит для меня как оператор switch для перечисления.Взгляните на класс enum , который неявно расширяется.У него есть метод ordinal, который используется для переключения.Вероятно, есть некоторые OrderType перечисления с константами LIMIT, MARKET, STOP и TAKE.

РЕДАКТИРОВАТЬ: На самом деле, я думаю, что немного больше информации было бы неплохо.Там есть дым и зеркала, которые используются для перечислений.Константа перечисления получает некоторый порядковый номер за экранами.Этот порядковый номер - то, что фактически используется в группе конструкций.При переключении на экземпляр enum компилятор фактически создает переключение над int (известной конструкцией, которая уже давно существует) с порядковым номером в качестве ввода.

Что происходит в ваших двух кодовых блоках:this: первый устанавливает «таблицу» (на самом деле просто массив) для порядковых номеров перечисления, если это еще не произошло.Там нулевая проверка.Если таблица пуста, она перейдет к метке _L2, чтобы выполнить заправку.В противном случае он переходит на метку _L1, которая просто возвращается.Второй блок кода (оператор фактического переключения) переключает int.Int получается из таблицы, получая элемент по индексу, который соответствует порядковому номеру константы перечисления.

Это кажется немного странным, но это создает некоторую косвенность между порядковыми номерами перечисления и используемыми значениямивнутренне с помощью коммутатора.

Теперь причина, по которой все выглядит так низкоуровнево, вместо простого просмотра переключателя перечисления, заключается в том, что перечисления были введены в JDK 1.5, но JAD некоторое время не обслуживалсяи только реально поддерживает декомпиляцию исходного кода до 1.4.Видя, как перечисления были реализованы с использованием конструкций, доступных в 1.4, декомпиляция действительно работает, но JAD ничего не знает о перечислениях, и поэтому не пытается представить это более разборчивым образом.

Вот чтоэтот второй блок кода, вероятно, выглядел так:

switch(co.getOrderType()) { //co.getOrderType() gets the OrderType of some variable
    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;
}
0 голосов
/ 22 июня 2013

При использовании метода getDeclaredFields () API отражения на Android, если анализируемый тип содержит переключатель enum, в котором enum объявлен в другом классе, одним из возвращаемых полей будет структура lazy SWITCH_TABLE, называемая чем-то вроде$SWITCH_TABLE$com$company$package$ClassName$EnumName.

Я использовал отражение для автоматического сопоставления полей класса с ContentValues перед сохранением в базу данных SQLite и просто потратил полдня на это, пытаясь выяснить, почему массив содержит столбецимена всегда были выключены одним.

...