Java必须编译为字节码吗?

时间:2017-11-29 10:43:22

标签: java bytecode jls language-implementation

Java语言规范是否要求将Java编译为Java字节代码?

根据我的理解,事实并非如此:

JLS 1

  

编译时间通常包含   将程序转换为与机器无关的字节代码[表示。

     

[...]

     

Java编程语言通常编译为字节码指令   Java Java虚拟机规范中定义的set和二进制格式   9版。

(强调我的)

我在规范中找不到任何其他提及的“字节码”或“字节码”。

这是否意味着所有字节码操作在技术上都不被JLS定义的“Java语言”所涵盖,并且在技术上依赖于实现细节?

2 个答案:

答案 0 :(得分:4)

您注意到正确的术语“正常”以及JLS中缺少任何字节代码描述旨在将Java编程语言定义为尽可能独立于执行环境。不过,这并不容易:

  

Relationship to Predefined Classes and Interfaces

     

如上所述,此规范通常是指Java SE平台API的类。特别是,某些类与Java编程语言有特殊的关系。示例包括ObjectClassClassLoaderStringThread等类,以及包java.lang.reflect中的类和接口等。此规范约束此类和接口的行为,但不提供完整的规范。读者可以参考Java SE平台API文档。

     

因此,本说明书没有详细描述反射。许多语言结构在Core Reflection API(java.lang.reflect)和语言模型API(javax.lang.model)中都有类似物,但这些通常不在这里讨论。例如,当我们列出可以创建对象的方式时,我们通常不包括Core Reflection API可以实现此目的的方式。读者应该了解这些额外的机制,即使文中没有提到它们。

因此Java编程语言不仅仅是JLS,它也是Java SE平台API。在那里,我们有所提到的defineClass类的ClassLoader方法,接受类文件格式的输入。因此,即使我们使用其他部署方式而不是字节码格式的类文件,完全兼容的环境也必须在此处支持该格式。请注意,Java 9引入了another method accepting input in the class file format,它甚至不需要Reflection或实现自定义类加载器。

这排除了JavaME,它没有JLS提到的这些API工件,否则,我们已经有了一个不支持字节码操作的Java环境的例子。

但是,这仍然没有完全回答字节码操作是否是非语言的问题,而是说JavaSE或EE。即使标准API提供对字节码格式的支持,字节码操作依赖于实现细节,其支持不是必需的Instrumentation API,也不是通过处理已部署形式的编译类文件,作为文件层次结构,jar文件或模块文件,既不保证是应用程序的部署形式(如开头所述)。因此,实现保证每个可能的Java环境一起使用的字节码操作工具确实是不可能的,尽管您必须花费很大的精力来创建一个{ {3}} ...

答案 1 :(得分:1)

JSL不必知道JVM将如何处理它,它只描述 Java语言。 JDK中提供的编译器(JAVAC)执行链接,但它不是语言本身的一部分

  

Oracle的JDK软件包含一个使用Java编程语言编写的源代码编译器到Java虚拟机的指令集

The Java™ Programming Language Compiler,中,我们可以找到相同的解释:

  

Java编程语言编译器javac读取用Java编程语言编写的源文件,并将它们编译成字节码类文件。可选地,编译器还可以使用Pluggable Annotation Processing API处理在源文件和类文件中找到的注释。编译器是命令行工具,但也可以使用Java Compiler API调用。 编译器接受Java语言规范(JLS)定义的源代码,并生成由Java虚拟机规范(JVMS)定义的类文件。

因此JAVAC命令主要是规范之间的桥梁。

  • 输入:JLS中的.java描述
  • 输出:JVMS中描述的.class。

您可以通过查看Jave Virtual Machine Specification找到一些信息。

  

Java虚拟机不知道Java编程语言,只知道特定的二进制格式,即类文件格式。类文件包含Java虚拟机指令(或字节码)和符号表,以及其他辅助信息。

(我想找到相反的说法,即Java语言对Java虚拟机语言一无所知......)

稍后在该规范中,我们发现了有关类格式以及语言如何被翻译到该说明列表的更多信息。