Java 字节码编译器必须比 Python 字节码编译器执行更多的检查。为了说明这一点,请取“hello world”程序中的这一行:
System.out.println("Hello World!");
要编译这一行代码,编译器必须找出其所有部分的含义。这比听起来更复杂:System
可能是一个包裹。或者它可以是一个类,或者在代码所在的同一个包中,或者在导入的包之一中,或者在java.lang
。因此编译器必须按顺序检查所有这些选项。一旦找到System
类,它必须检查其访问修饰符是否允许这种使用。
之后,编译器必须弄清楚什么out
是:它是嵌套类还是类成员,它的访问修饰符是什么?编译器发现它是一个静态成员变量,PrintStream
类型。然后它必须做同样的检查println
。编译器在知道所有这些之前无法为这行代码发出任何代码,因为生成的字节代码根据所涉及的对象的类型而不同。
所有这些检查都需要时间,最重要的是,即使对于最简单的程序,编译器也必须从标准库加载大量的类定义。
相比之下,Python字节码编译器只需要解析该行,就可以立即生成代码,而无需查看额外的模块。在 Python 中,代码将被编译为:
- 从当前范围(LOAD_NAME)查找“系统”对象
- 从系统中查找“out”属性(LOAD_ATTR)
- 从“out”查找“println”(LOAD_METHOD)
- 生成代码来调用它(CALL_METHOD)
Python 编译器并不关心其中一些查找在运行时是否失败。
另一个重要的区别是 Java 编译器完全用 Java 编写,并在运行时编译为机器代码,而 CPython 的大部分实现是提前编译的 C 代码。这意味着与Python相比,Java存在一点“冷启动”问题。
Update:从 Java 9 开始,您可以直接从源代码运行 java 程序,而无需将其编译为字节代码。运行一个简单的“hello world”程序可以让您了解通过提前将 Java 编译为字节代码可以节省多少成本,即使对于一个简单的程序也是如此:
- 根据测量,Python 程序的运行时间为 45-50 毫秒
time python hello.py
.
- Java程序无需提前编译为字节码根据测量,运行时间为 350-400 毫秒
time java Hello.java
- 编译为字节码后的 Java 程序运行时间为 70-80 毫秒,测量结果为
time java Hello
免责声明:没有遵循科学方法或进行统计分析,所以对此持保留态度。测试环境:Python版本3.8.5、Java版本11.0.8、Fedora 32、Intel i7 8750H CPU
你好.py:
print("hello world")
你好.java:
public class Hello {
public static void main(String[] args) {
System.out.println("Hello world");
}
}