-1

我碰壁了,试图用 Java 编写一个简单的编译器,使用 ASM。基本上,我正在尝试将字符串添加在一起,但无法弄清楚为什么我的代码无法这样做。问题在于以下代码行的编译方式:

char[] p;
p = "Hi";
p = p + i[0];

其中 i 是一个已初始化的数组。行p = "Hi"; 编译为:

bipush 2;
newarray t_char;
dup;
bipush 0;
ldc h;
castore;
dup;
bipush 1;
ldc i;
castore;

请注意,我故意将字符串“Hi”视为 char 数组,而不是直接视为 String 对象。反编译的时候是这样的:

Object localObject1 = { 'H', 'i'};

因此,由于 {'H', 'i'} 不是 Object 的正确构造函数,因此程序不会执行。现在,我的困惑,以及我来到stackoverflow的原因是当行p = p + i[0]; 从程序中删除,或替换为不使用数组的,例如p = p + 5;, 行p = "Hi"; 再次以完全相同的方式编译:

bipush 2;
newarray t_char;
dup;
bipush 0;
ldc h;
castore;
dup;
bipush 1;
ldc i;
castore;

反编译时,同一行内容如下:

char[] arrayOfChar1 = {'H', 'i'};

程序运行得很好。我完全不知道这里发生了什么,也不知道如何解决它。为了反编译 .class 文件,我使用了这个反编译器。我想知道为什么在这两种情况下完全相同的字节码反编译不同。

4

1 回答 1

0

通常,您不能期望能够重新编译反编译的代码。编译和反编译都是有损过程。特别是,字节码不必像 Java 源代码那样包含显式类型,并且字节码的类型检查规则比源代码级别的类型系统要宽松得多。

这意味着在反编译代码时,反编译器必须猜测局部变量的类型(除非编译的类中包含可选的调试元数据)。在某些情况下,它会猜到Object,这会导致编译错误。在其他情况下,它猜测char[]。如果您想要更深入的解释,您可以深入研究反编译器源代码,但真正的问题是期望反编译器在没有类型信息的情况下神奇地给出良好的结果。

无论如何,如果你想编辑已经编译的代码,你不应该使用反编译器。您最好的选择是使用像Krakatau这样的汇编器/反汇编器对,它允许您在字节码级别无损地编辑类文件(假设您了解字节码)。

于 2018-06-19T01:44:57.633 回答