编译Java文件时,它将生成一个.class文件。现在,此.class文件具有JVM解释的字节码。当我们在文本编辑器中打开.class文件时,它不是人类可读的。现在要查看字节码,可以使用像javap这样的反汇编程序。
我的问题是,为什么我们需要分解字节码才能查看字节码本身?
反汇编程序实际上是如何将.class文件转换为人类可读格式的?
Java虚拟机模拟一台计算机。这就是为什么它被称为 机器的原因 ,尽管它是硬件中不存在的 虚拟 机器 。因此,在考虑 javap
outout与实际Java字节码的区别时,请考虑汇编代码与机器代码之间的区别:
汇编代码使用所谓的 助记符
使代码易于阅读。但是,此类助记符名称与机器无关,因为机器仅知道如何读取和操作二进制数据。因此,我们必须使用来组装助记符(及其潜在的参数) 汇编
其中每个这样的助记符被转换成其二进制等效。例如,要从特定寄存器加载值,我们将load 0xFF
在汇编中编写类似的内容,而不是对该指令使用实际的二进制操作码(可能类似于)1001 1011 1111 1111
。同样,对于Java字节码,助记符就是 javap
产生的数据,我们需要将二进制数据表示给(虚拟)计算机,然后可以对其进行处理。仅当我们想读取字节码时,我们才将其反汇编为 javap 表示的汇编代码。
请记住:存在汇编语言和 javap
输出的唯一原因是这样的事实,例如您和我这样的人不喜欢阅读二进制代码。我们受过训练,可以区分形状,例如字母和名称。相反,机器通过读取位流来顺序解释数据。如前所述,这些位使我们难以阅读,这就是为什么我们宁愿以十六进制格式显示它们:而不是1111 1111
,我们宁愿编写0xFF
。但这仍然很难读取,因为这样的数值并不能揭示其上下文含义。0xFF
仍然意味着一切。这就是为什么我们宁愿在隐含此含义的地方使用提到的助记符。
您可能会争辩说,虚拟机仍然只是虚拟机,因此该计算机确实可以解释助记符,而不是二进制Java 字节码
。但是,这种助记符将占用更多空间(html" target="_blank">字符串当然只是由机器表示为字节),并且比在JVM上运行的模拟机器语言还要花费更多的时间来解释。因此,与标准编码(例如ASCII)相比,字符集仅包含单词而不是字母(其中单词仅是Java虚拟机使用和理解的那些字母),您还可以认为字节码是一种奇怪的编码。显然,此
Java字节码字符集 比使用ASCII来描述类文件的内容更有效。
所以我尝试从Windows迁移到Linux。今天我尝试用Emacs而不是Windows IDE编写和编译东西。这是我的示例代码: 这是我使用esc-x从emacs编译的- 在终端上,我使用“hello”执行hello/你好。然后我把代码改成了“cout” 它为什么这么做?
每次我试图编译它来测试它不recongnise文件
问题内容: 这是代码片段。 编辑:我正在从目录中读取文件。因此,我需要在每个循环中打开阅读器。我进行了一些修改,但同时也没有写入该文件。这是代码: 编辑:我修改了代码,但没有成功, 而且我收到此错误: 编辑:谢谢..我想通了。实际上,我在eclipse中创建了一个目录,但没有刷新它来查看内容。真是太傻了…还是非常感谢 问题答案: 您正在循环内创建FileWritter,因此您将始终在每个循环中截断
问题内容: 从Effective Java Second Edition的第28项开始:“不要将通配符类型用作返回类型。与其为用户提供额外的灵活性,不如将其强制在客户端代码中使用通配符类型。” 我刚开始接触通用通配符,以了解我在编写的一段代码中最后一次未经检查的强制转换警告,而且我不明白为什么getRawType()返回通配符类型。 我必须转换token.getRawType()因为它返回一个 问
我正在编写一个小的Java库,其中包含我通常在大多数android应用程序中包含的相关代码。我决定将库导出为一个jar文件,然后将该文件放到我未来项目的libs文件夹中。 null 现在,当我在我的一个android应用程序中使用这个jar时,除了Doc部分之外,所有的一切都像预期的那样运行。当我悬停在我的库的类和方法上时,我看不到我编写的文档注释。 Q1:我是不是又少了一步? Q2:jar文件应
问题内容: 我希望从编译时以及运行时的角度来看,提供正确类型的返回值都不会成为问题。 但是我一定是错的。 编辑: 它不与和。 问题答案: 根据该方法的Javadoc: 实际结果类型为| X | 是擦除其上调用的表达式的静态类型。例如,此代码段中不需要强制转换 在此,您的代码段中的值为,因此只能分配给或。 使用这种特定措辞的原因是因为当您说该变量具有类型T其中where时,可以存在多个扩展的类,因此