编译Java文件时,它将生成一个.class文件。现在,此.class文件具有JVM解释的字节码。当我们在文本编辑器中打开.class文件时,它不是人类可读的。现在要查看字节码,可以使用像javap这样的反汇编程序。
我的问题是,为什么我们需要分解字节码才能查看字节码本身?
反汇编程序实际上是如何将.class文件转换为人类可读格式的?
Java虚拟机模拟一台计算机。这就是为什么它被称为 机器的原因 ,尽管它是硬件中不存在的 虚拟 机器 。因此,在考虑 javap outout与实际Java字节码的区别时,请考虑汇编代码与机器代码之间的区别:
汇编代码使用所谓的 助记符 使代码易于阅读。但是,此类助记符名称与机器无关,因为机器仅知道如何读取和操作二进制数据。因此,我们必须使用来组装助记符(及其潜在的参数) 汇编 其中每个这样的助记符被转换成其二进制等效。例如,要从特定寄存器加载值,我们将load 0xFF在汇编中编写类似的内容,而不是对该指令使用实际的二进制操作码(可能类似于)1001 1011 1111 1111。同样,对于Java字节码,助记符就是 javap 产生的数据,我们需要将二进制数据表示给(虚拟)计算机,然后可以对其进行处理。仅当我们想读取字节码时,我们才将其反汇编为 javap 表示的汇编代码。
load 0xFF
1001 1011 1111 1111
请记住:存在汇编语言和 javap 输出的唯一原因是这样的事实,例如您和我这样的人不喜欢阅读二进制代码。我们受过训练,可以区分形状,例如字母和名称。相反,机器通过读取位流来顺序解释数据。如前所述,这些位使我们难以阅读,这就是为什么我们宁愿以十六进制格式显示它们:而不是1111 1111,我们宁愿编写0xFF。但这仍然很难读取,因为这样的数值并不能揭示其上下文含义。0xFF仍然意味着一切。这就是为什么我们宁愿在隐含此含义的地方使用提到的助记符。
1111 1111
0xFF
您可能会争辩说,虚拟机仍然只是虚拟机,因此该计算机确实可以解释助记符,而不是二进制Java 字节码 。但是,这种助记符将占用更多空间(字符串当然只是由机器表示为字节),并且比在JVM上运行的模拟机器语言还要花费更多的时间来解释。因此,与标准编码(例如ASCII)相比,字符集仅包含单词而不是字母(其中单词仅是Java虚拟机使用和理解的那些字母),您还可以认为字节码是一种奇怪的编码。显然,此 Java字节码字符集 比使用ASCII来描述类文件的内容更有效。