用JAD反编译java - 限制

Grz*_*nio 4 java decompiling jad

我正在尝试使用Java中的JAD反编译几个jar文件(我尝试使用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;
}
Run Code Online (Sandbox Code Playgroud)

使用如下:

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;
        }
Run Code Online (Sandbox Code Playgroud)

知道这个结构本来可以是什么吗?

kan*_*kan 7

我认为它是枚举的表格开关.它将任意枚举序数值转换为数字0..n,它可以提高switch语句的性能.

更新 刚才明白了!问题是 - 使用枚举的代码可以与枚举本身分开编译.所以它在编译时不知道序数值,所以它不能构造一个合适的tableswitch op.所以,这就是为什么它引入了懒惰的SWITCH_TABLE结构来将当前可用的序数值映射到本地tableswitch int数字.


G_H*_*G_H 5

在我看来就像枚举上的switch语句.看一下enum类,它枚举隐式扩展.它有ordinal用于切换的方法.可能有一些OrderType常量限制,市场,停止和TAKE的枚举.

编辑:其实,我猜一些更多的信息会很好.有一些烟雾和镜子用于像枚举这样的东西.枚举常量在屏幕后面获得一些序数.这个序数是在一堆构造中实际使用的.当切换枚举实例时,编译器实际上创建了一个int(一个众所周知的构造已经存在一段时间)的开关,并以序数作为输入.

在你的两个代码块中会发生什么:第一个为枚举数设置一个"表"(实际上只是一个数组),如果这还没有发生的话.有一个空检查.如果表为null,它将跳转到标签_L2以进行启动.否则,它跳转到_L1只返回的标签.第二个代码块(实际的switch语句)对int进行了切换.通过获取与枚举常量的序数对应的索引处的元素,从表中获取int.

这看起来有点奇怪,但这会在枚举和交换机内部使用的值之间形成某种间接.

现在,这一切看起来如此低级而不是简单地看到enum上的开关的原因是在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;
}
Run Code Online (Sandbox Code Playgroud)