我试图在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;
}你知道这个结构最初是什么吗?
发布于 2011-10-24 18:15:24
我认为它是枚举的tableswitch。它将任意枚举序数值转换为数字0..n,从而提高了switch语句的性能。
UPDATE刚刚理解了!问题是-使用枚举的代码可以与枚举本身分开编译。所以它在编译时不知道序数值,所以它不能构造一个合适的表切换操作。因此,这就是为什么它引入了惰性SWITCH_TABLE结构来将当前可用的序数值映射到本地表交换整型数字。
发布于 2011-10-24 17:55:54
在我看来,它像是枚举上的switch语句。看一下枚举隐式扩展的enum class。它具有用于切换的ordinal方法。可能有一些带有常量LIMIT、MARKET、STOP和TAKE的OrderType枚举。
编辑:事实上,我猜更多的信息会更好。有一些烟雾和镜子被用来做枚举之类的东西。枚举常量在屏幕后面获取一些序号。这个序数是在一系列构造中实际使用的数字。在切换enum实例时,编译器实际上创建了一个以序数作为输入的int (一个已经存在了一段时间的众所周知的构造)上的切换。
在你的两个代码块中发生的事情是这样的:第一个代码块为枚举序数建立一个“表”(实际上只是一个数组),如果这还没有发生的话。有一个空检查。如果表为空,它将跳转到标签_L2进行初始化。否则,它会跳转到简单返回的标签_L1。第二个代码块(实际的switch语句)在int上执行switch。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;
}发布于 2013-06-22 05:06:45
在Android上使用反射API的getDeclaredFields()方法时,如果被内省的类型包含枚举开关,其中枚举在另一个类中声明,则返回的字段之一将是惰性SWITCH_TABLE结构,称为类似$SWITCH_TABLE$com$company$package$ClassName$EnumName的内容。
在保存到SQLite数据库之前,我使用反射将类的字段自动映射到ContentValues,并花了半天的时间尝试弄清楚为什么保存列名的数组总是少了一个。
https://stackoverflow.com/questions/7873725
复制相似问题