创建 char 数组会生成 java 字节码中的对象



我遇到了一堵墙,试图用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"视为字符数组,而不是直接视为 String 对象。反编译时,它读作:

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

因此,由于 {'H', 'i'} 不是 Object 的正确构造函数,因此程序不会执行。现在,我的困惑,以及我来堆栈溢出的原因是,当行 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文件,我正在使用这个反编译器。 我想知道为什么完全相同的字节码在这 2 种情况下反编译不同。

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

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

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

相关内容

  • 没有找到相关文章

最新更新