编译java文件时,会生成.class文件。现在这个.class文件具有JVM解释的字节码。当我们在文本编辑器中打开.class文件时,它不是人类可读的。现在要查看字节码,可以使用像javap这样的反汇编程序。
我的问题是,为什么我们需要反汇编字节码才能查看字节码本身?
反汇编程序实际上做了什么,将.class文件转换为人类可读的格式?
答案 0 :(得分:5)
Java虚拟机模拟机器。这就是它被称为机器的原因,尽管它是硬件中不存在的虚拟。因此,在考虑 javap outout与实际Java字节代码的区别时,请考虑程序集和机器代码之间的区别:
汇编代码使用所谓的助记符来使代码具有人类可读性。然而,这样的助记符名称与机器无关,因为机器只知道如何读取和操作二进制数据。因此,我们必须使用汇编程序来组装助记符(及其潜在参数),其中每个这样的助记符都被转换为其二进制等价物。例如,为了从特定寄存器加载值,我们将在汇编中编写类似load 0xFF
的内容,而不是使用此指令的实际二进制操作码,这可能类似于1001 1011 1111 1111
。类似地,对于Java字节代码,助记符是 javap 产生的,我们需要将二进制数据表示给它可以处理的(虚拟)机器。只有当我们想要读取字节代码时,我们才会将其反汇编为 javap 所代表的汇编代码。
请记住:汇编语言和 javap 输出存在的唯一原因是像你我这样的人不喜欢阅读二进制代码。我们接受培训,以区分我们所看到的形状,例如字母和名称。相反,机器通过读取比特流来顺序地解释数据。如上所述,我们很难阅读这些内容,这就是为什么我们宁愿以十六进制格式呈现它们:我们宁愿写1111 1111
而不是0xFF
。但这仍然很难阅读,因为这样的数值并没有揭示其背景意义。 0xFF
仍然可能意味着一切。这就是为什么我们宁愿使用所提到的助记符,其含义是隐含的。
您可能会认为虚拟机仍然只是虚拟机,因此该机器确实可以解释助记符而不是二进制Java 字节代码。但是,这样的助记符会消耗更多空间(字符串当然只是由机器表示为字节),并且它还需要比在JVM上运行的模拟机器语言更多的时间来解释。因此,与标准编码(例如ASCII)相比,您可以将字节代码视为奇怪的编码,其中字符集仅包含字而不是字母,其中字仅是Java虚拟机使用和理解的字。显然,这个 Java字节代码字符集比使用ASCII描述类文件的内容更有效。
答案 1 :(得分:3)
在保存数据时,可用格式分为两大类:
.class
文件主要用于提供给JVM ,因此它应该是机器中最小且最容易阅读的可能格式。 如果.class
文件是文本文件(如果字节码以人类可读的形式保存),则每次.class
文件时都需要解析但是,这个功能并不经常需要,因此浪费应用程序的加载时间。
答案 2 :(得分:1)
.class只是机器可读的目标代码。如果您想查看代码,那么您可以使用任何反编译器,如Jad Decompiler
等。
答案 3 :(得分:1)
一个class file包含一堆命令/操作码/数据,这些命令/操作/数据是由JVM读取的,当人类查看时,它们大部分只是一大堆数字和数据。嵌入无意义的文本。
你需要反汇编阅读这个的原因是因为反汇编程序以对人类有意义的方式组织它并用textual commands代替数字(例如opcodes的文本版本aload
代替\19
或goto
代替\A7
),这对人类更有意义。
答案 4 :(得分:0)
java编译器所做的是解释您的Java语法并将其转换为虚拟机可以理解的语句。该虚拟机是用C和Java组合编写的。虚拟机将字节码指令转换为操作系统的本机调用。 (这就是为什么Windows的JVM与基于unix的系统的JVM不同)
正如在评论中已经说明的那样,解释人类可读代码比解释已经部分原生的指令要慢。