所以我试图对编译的java程序进行轻微的有效法律更改。我正在使用JD-GUI for Mac反编译它。在大多数情况下,反编译的代码没有错误,但是有一些奇怪的东西,如未声明的变量,多个相同的变量声明以及一些不易编译的奇怪语句。 反编译代码中的一些奇怪的陈述真的令人费解。我特别遇到一个switch语句有问题:
switch ($SWITCH_TABLE$PackageName$ClassName$InnerEnumName()[getPlatform().ordinal()])
其中PackageName.ClassName是此语句所在的类,而InnerEnumName是ClassName中的内部枚举。 另请注意,getPlatform()是ClassName中的一个方法,它返回一个类型为InnerEnumName的枚举
奇怪的是,当我刚刚删除了这类有问题的语句,编译它并将其重新插入程序时,它开始工作但有一些奇怪的错误。 例如,当我将switch语句更改为
时 switch (getPlatform().ordinal())
它开始打击案例3(第三种情况和第3种情况),当它应该打到案例4时(再次是第四种情况以及价值4的情况)
答案 0 :(得分:2)
反编译总是不完美的。反编译器必须采用字节码并对原始源进行反向工程,找出循环的位置,循环控制的内容等等。我绝不会期望它对于非平凡的程序是完美的。
对于$ names,这些是在“伪造”内部类的过程中内部生成的名称(因为JVM实际上不支持内部类)。反编译器显然做了一个不完美的工作,弄清楚内部类是什么,并适当地命名它们和编译器创建的伪造东西的对象。熟悉字节码格式的人可能会很快地解决问题,但是,和其他人一样,这是非常重要的。
(在这种特殊情况下,由于某种原因,编译器似乎创建了一个从内部枚举值到其他值的映射表,当你“删除”该语句时,你丢失了该映射。)
[我要补充说,反编译器的一个大问题是javac是一个如此移动的目标。特别是像内部类实现这样的东西正在不断调整,所以一周工作的可能会在下一个版本中失败,编译器的下一个+.001版本。]
答案 1 :(得分:1)
JD-GUI(JD?)似乎有问题。试着找一个更好的反编译器?太糟糕的jad古老了 - 它过去很好。
答案 2 :(得分:1)
冒着复活古老问题的风险 - 通过剥离序数上的数组间接,原始开关的含义会发生变化。
我在这里写了这个: http://www.benf.org/other/cfr/switch-on-enum.html
突出的一点是:
第一个枚举 - >想到的整数函数是.ordinal()。但是 - 这有几个问题:
我们正在启用的枚举类没有修复 - 我们不能为case语句获取目标序列的副本 - 有人可能会更改枚举的定义! 有人甚至可能会删除我们用作案例标签的字段。
所以我们需要一个查找函数,它不依赖于修复的枚举值的序数(即在运行时解析它),并且可以处理要删除的枚举字段。
因此您删除了数组 - 它是枚举语句中的序数与switch语句中的位置之间的运行时映射。
这里真正有趣的是,这意味着Javac为每个开关创建了一个额外的内部类 - Fun!