使用JAD限制反编译java

使用JAD限制反编译java,java,decompiling,jad,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:

我正在尝试用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;
}
其用途如下:

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

知道这个构造最初可能是什么吗?

在我看来就像枚举上的switch语句。看一看枚举隐式扩展的。它具有用于切换的
ordinal
方法。可能有一些
OrderType
enum带有常量LIMIT、MARKET、STOP和TAKE

编辑:事实上,我想更多的信息会更好。有一些烟雾和镜子被用于枚举之类的东西。枚举常量在屏幕后面获取一些序号。这个序数实际上是在一堆构造中使用的。在切换枚举实例时,编译器实际上会创建一个切换int(一个众所周知的结构,已经存在了一段时间)的开关,并将序号作为输入

在您的两个代码块中发生的是:第一个代码块为枚举序号设置一个“表”(实际上只是一个数组),如果这还没有发生的话。有空支票。如果该表为空,它将跳转到label
\u L2
进行启动。否则,它将跳转到标签
\u L1
,并简单返回。第二个代码块(actualy switch语句)对int进行切换。int是通过从表中获取与枚举常量序号对应的索引处的元素而获得的

这似乎有点奇怪,但这在枚举序号和开关内部使用的值之间形成了某种间接关系

现在,这一切看起来都是低级的,而不是简单地在枚举上看到一个开关,原因是枚举是在JDK1.5中引入的,但是JAD已经有一段时间没有维护了,只支持反编译源代码,直到1.4。看到Enum是如何使用1.4中提供的构造实现的,反编译确实有效,但JAD不了解Enum,因此没有努力以更清晰的方式表示

下面是第二个代码块可能的样子:

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..n,从而提高switch语句的性能

更新 我明白了!
问题是-使用枚举的代码可以与枚举本身分开编译。因此,它在编译时不知道序数值,因此无法构造正确的表切换操作。因此,这就是为什么它引入了惰性切换表结构,将当前可用的序数值映射到本地表切换整数。

在Android上使用反射API的getDeclaredFields()方法时,如果要内省的类型包含枚举开关,其中枚举在另一个类中声明,则返回的字段之一将是惰性开关表结构,称为类似
$switch\u TABLE$com$company$package$ClassName$EnumName


在保存到SQLite数据库之前,我使用反射自动将类的字段映射到
ContentValues
,我花了半天的时间试图弄清楚为什么保存列名的数组总是关闭一个。

有一件事让我感到奇怪,为什么它会创建表,只是不直接使用enum的序数(它们已经是
int
s了)?很好的展示!我不知道它为什么会引入这种间接方式,但这很好地解释了它。