我尝试使用ASM编写一个简单的Java编译器。基本上,我试图将字符串添加到一起,并且无法解决为什么我的代码无法这样做。问题在于如何编译以下代码行:
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文件,我使用的是this反编译器。 我想知道为什么在这两种情况下完全相同的字节码反编译不同。
答案 0 :(得分:0)
通常,您不能指望能够重新编译反编译代码。编译和反编译都是有损进程。特别是,字节码不必像Java源代码那样包含显式类型,字节码的类型检查规则比源级类型系统要宽松得多。
这意味着在反编译代码时,反编译器必须猜测局部变量的类型(除非编译类包含可选的调试元数据)。在某些情况下,它猜到了Object
,这导致了编译错误。在其他情况下,它猜测char[]
。如果你想要更深入的解释,你可以深入了解反编译器源代码,但真正的问题是期望反编译器在没有类型信息的情况下神奇地给出好的结果。
无论如何,如果你想编辑已编译的代码,你不应该使用反编译器。最好的办法是使用汇编程序/反汇编程序对Krakatau,它允许您在字节码级别无损地编辑类文件(假设您理解字节码)。