反编译Java类产生不同的输出结果

3

出于好奇,我使用 DJ Java DecompilerCAVAJ Java Decompiler 对以下代码进行了反编译(Java 版本为 1.7)。


    byte a = 10;
    a = (byte) (a +1);

    byte b = 10;
    b = b++;

    byte c = 10;
    c +=c;

    System.out.printf("a=%d \t b=%d \t c=%d\n",a,b,c);

以下内容显示输出为:a=11 b=10 c=20



以下是反编译的内容:

    byte a = 10;
    a++;
    byte b = 10;
    b++;
    b = b;
    byte c = 10;
    c += c;
    System.out.printf("a= %d \t b = %d \t c = %d\n", new Object[] {
        Byte.valueOf(a), Byte.valueOf(b), Byte.valueOf(c)
    });

当用作源代码输出时,其输出如下所示:a=11 b=11 c=20
更清晰地说,这与byte没有任何关系,对于int也会发生同样的事情,我甚至在在线编译器IDEONE中检查了以上代码,并得到了与我的输出相同的结果。
那么,反编译器是产生了错误的代码,还是其他问题?

1
我不明白为什么第二种情况下输出中的额外空格消失了。 - Denys Séguret
2
这个问题可能应该在CAVAJ的论坛上讨论,因为它看起来像是反编译错误。 - Denys Séguret
@Anony-Mousse 我想他担心的是反编译器将 b=b++; 更改为 b++;b=b; - Denys Séguret
是的,看起来像是CAVAJ的一个bug。在这里我们无法提供任何帮助。 - Has QUIT--Anony-Mousse
那么,把查询放到CAVAJ上会更好吗? - exexzian
显示剩余2条评论
2个回答

4
我会给你一个简短的答案:是的,似乎反编译器正在生成错误的代码。因为这个原因:
byte b = 10;
b = b++;

具有强烈的预测行为(b 不会改变)。

更新:此外,没有任何一个反编译工具可以给你生成的反编译代码正确性的 100% 保证。

更新2:您确定提供给我们的是实际版本的代码吗?因为这个:

byte aa = 10;
a = (byte) (a +1);

当然是一个错误。它甚至无法编译 :)

更新-3 好吧,我需要说的是,Jad反编译器(Jad 1.5.8g适用于Intel平台的Windows 9x / NT / 2000)生成相同的代码:

    byte b = 10;
    b++;
    b = b;

...

    java.lang.System.out.printf("a=%d \t b=%d \t c=%d\n", new java.lang.Object[] {...

但是,这并不奇怪:Cavaj Java反编译器使用Jad作为其Java反编译引擎

结论:将此行为视为Jad反编译器的特性/缺陷,该反编译器远非完美。


等待10分钟,我会自己检查一下 :) - Andremoniy
@sansix,请查看我的UPD-2,你的代码有一些错误。 - Andremoniy
@Andremoniy +1 同意 b = b++; 这个表达式的行为是可以预测的,所以可能是反编译器的 bug。 - exexzian
1
@dystroy,这也是给你的信息:我检查了这个案例,确实是Jad的缺陷。 - Andremoniy
1
另一方面,他们可能会解释说他们的反编译器帮助 OP 找到了代码中的一个 bug... - Denys Séguret
显示剩余2条评论

-2

这不是关于反编译器的问题。当您使用Java编译器编译代码时,在某些情况下,编译器会更改您的代码并将其优化为另一种不会改变结果的代码。您的代码如下:

byte a = 10;
a = (byte) (a + 1);

在这种情况下,Java编译器知道无需在byte和byte之间进行类型转换,因此编译器尝试删除您的类型转换,并在此过程中使用最接近其理解的代码替换您的代码。 这是编译器的输出:
byte a = 10;
a++;

所以,这不是关于反编译过程。Java编译器会更改您的代码。


你的意思是说这里不需要进行类型转换 a = (byte) (a + 1); 吗? - exexzian
亲爱的,我们现在来讨论这个问题:b = b++; - Andremoniy
答案是一样的。b = b++; 在编译过程中会被改变,而不是反编译。这段代码将被替换为 b++;,是的,不需要进行类型转换。 - S.Yavari
当你编写像 byte a = 0; a = (byte) (a + 1); 这样的代码时,编译器会知道你想要执行 a++;,并且它会改变你的代码并将其优化为 a++;。在你的版本中需要进行强制类型转换,但在编译版本中不需要,结果是相同的。然后编译器只需将您的代码更改为优化版本。 - S.Yavari
一些Java开发工具包的发行版中包括一个名为javac_g的备用Java编译器。这个版本的Java编译器生成的代码不包含标准javac编译器执行的某些内部优化。如果您的JDK发行版中包含此编译器,请务必在编译调试代码时使用它。否则,对于所有发布的代码,请坚持使用javac编译器。 - S.Yavari
1
@SasanYavari 用 b++; b = b; 替换 b = b++; 不是一种优化。 - Denys Séguret

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接