例如,假设您有一个简单地打开一个窗口的 java 程序。这显然会导致针对不同操作系统的不同汇编代码(在 Windows 上它最终必须调用 CreateWindowEx)。那么 Java 字节码(或任何其他类似的语言)如何代表特定于平台的东西呢?
4 回答
JVM 是依赖于操作系统的,字节码不是。
这意味着字节码是一种“通用”语言,JVM 将根据其运行的系统解释最终执行。
更新
正如 Chris Jester-Young 所说,我的回答并不完全正确:
- 100% 纯 Java 程序的字节码确实与平台无关。此类程序调用的底层 Java 平台类当然不是。
- 大多数时候,JVM 也会 JIT 编译,而不仅仅是解释。(您可以启用纯解释模式,但它会很慢!)
宁静是这么说的:
通常,编译后的代码是 CPU“执行”程序所需的确切指令集。在 Java 中,编译后的代码是一组精确的“虚拟 CPU”指令集,需要在每台物理机器上进行相同的工作。
因此,在某种意义上,Java 语言的设计者决定该语言和编译后的代码将独立于平台,但由于代码最终必须在物理平台上运行,他们选择将所有平台相关的代码放在JVM。
JVM 的这一要求与您的 Turbo C 示例相反。使用 Turbo C,编译器将产生平台相关的代码,并且不需要类似 JVM 的工作,因为编译后的 Turbo C 程序可以直接由 CPU 执行。
对于 Java,CPU 执行依赖于平台的 JVM。这个正在运行的 JVM 然后执行独立于平台的 Java 字节码,前提是您有一个可用的 JVM 来执行它。您可能会说,编写 Java 代码,您不会编写要在物理机上执行的代码,而是编写要在 Java 虚拟机上执行的代码。
所有这些 Java 字节码都可以在所有 Java 虚拟机上运行的唯一方法是为 Java 虚拟机的工作方式编写了一个相当严格的标准。这意味着无论您使用什么物理平台,Java 字节码与 JVM 接口的部分都保证只能以一种方式工作。由于所有 JVM 的工作方式完全相同,因此相同的代码在任何地方都完全相同,无需重新编译。如果您无法通过测试以确保其相同,则不允许将您的虚拟机称为“Java 虚拟机”。
当然,有一些方法可以破坏 Java 程序的可移植性。您可以编写一个程序来查找仅在一个操作系统上找到的文件(例如 cmd.exe)。您可以使用 JNI,它有效地允许您将已编译的 C 或 C++ 代码放入一个类中。您可以使用仅适用于特定操作系统的约定(例如假设“:”分隔目录)。但是你可以保证永远不必为不同的机器重新编译你的程序,除非你正在做一些非常特别的事情(比如 JNI)。
在 Java 编程语言中,所有源代码首先编写成以 .java 扩展名结尾的纯文本文件。这些源文件然后由 javac 编译器编译成 .class 文件。.class 文件不包含处理器本机的代码;相反,它包含字节码——Java 虚拟机 1 (Java VM) 的机器语言。然后,java 启动器工具使用 Java 虚拟机的实例运行您的应用程序。
.class files
( i.e byte code
) 是相同的,但不是JVM
,它与操作系统不同。
There are different Java Virtual Machine binaries for each operating system. They can run the same Java bytecode (classes, jars), but the implementations is sometimes different.
For example, all the window handling code is implemented differently on Windows, Unix and Mac. Each of them will call the OS native calls to open a window or to draw something. You don't have to care about it, because the Virtual Machine automatically does it.