拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 Java是编译语言还是解释语言?

Java是编译语言还是解释语言?

白鹭 - 2021-11-24 500 0 0

1.概述

编程语言根据其抽象级别进行分类。我们区分高级语言(Java,Python,JavaScript,C ++,Go),低级语言(汇编程序),最后是机器代码。

每个高级语言代码(例如Java)都需要转换为机器本地代码才能执行。该翻译过程可以是编译或解释。但是,还有第三种选择。试图利用两种方法的组合。

在本教程中,我们将探讨如何在多个平台上编译和执行Java代码。我们将研究一些Java和JVM设计细节。这些将帮助我们确定Java是编译,解释还是两者的混合。

2.编译与解释

让我们开始研究编译和解释编程语言之间的一些基本差异。

2.1。编译语言

编译器将编译语言(C ++,Go)直接转换为机器本机代码。

在执行之前,它们需要明确的构建步骤。这就是为什么每次更改代码时都需要重建程序。

编译语言往往比解释语言更快,更有效**。**但是,它们生成的机器代码是特定于平台的。

2.2。解释型语言

另一方面,在解释语言(Python,JavaScript)中,没有构建步骤。相反,解释器在执行程序时对程序的源代码进行操作。

曾经认为口译语言比编译语言要慢得多。但是,随着实时(JIT)编译的发展,性能差距正在缩小。但是,我们应该注意,JIT编译器在程序运行时将代码从解释语言转换为机器本地代码。

此外,我们可以Windows,Linux或Mac等多个平台上执行解释后的语言代码。解释的代码与特定类型的CPU体系结构没有关联。

3.写一次即可在任何地方运行

Java和JVM在设计时考虑了可移植性。因此,当今大多数流行的平台都可以运行Java代码。

这听起来似乎暗示着Java是一种纯解释性语言。但是,在执行之前,需要将Java源代码编译为字节码。字节码是JVM固有的一种特殊机器语言. JVM在运行时解释并执行此代码。

是为支持Java的每个平台(而不是我们的程序或库)构建和定制的JVM。

现代JVM也具有JIT编译器。这意味着JVM在运行时优化我们的代码,以获得与编译语言相似的性能优势。

4. Java编译器

javac命令行工具将Java源代码编译成包含平台无关字节码的Java类文件

$ javac HelloWorld.java

源代码文件带有.java后缀,而包含字节码的类文件则由生成。 class后缀。

Java是编译语言还是解释语言?

5. Java虚拟机

编译的类文件(字节码)可以由Java虚拟机(JVM)执行:

$ java HelloWorld Hello Java!

现在让我们更深入地研究JVM体系结构。我们的目标是确定在运行时如何将字节码转换为机器本机代码。

5.1。架构概述

JVM由五个子系统组成:

  • 类加载器
  • JVM内存
  • 执行引擎
  • 本机方法接口和
  • 本机方法库

Java是编译语言还是解释语言?

5.2。类加载器

JVM利用ClassLoader子系统将已编译的类文件带入**JVM内存**。

除加载外,ClassLoader还执行链接和初始化。那包括:

  • 验证字节码是否存在安全漏洞
  • 为静态变量分配内存
  • 用原始引用替换符号内存引用
  • 将原始值分配给静态变量
  • 执行所有静态代码块

5.3。执行引擎

执行引擎子系统负责读取字节码,将其转换为机器本机代码并执行。

三个主要组件负责执行,包括解释器和编译器:

  • 由于JVM与平台无关,因此它使用解释器执行字节码
  • JIT编译器通过将字节码编译为本地代码以重复方法调用来提高性能
  • 垃圾收集器收集并删除所有未引用的对象

执行引擎利用本机方法接口(JNI)来调用本机库和应用程序。

5.4。实时编译器

解释器的主要缺点是,每次调用方法时,都需要解释,这可能比编译的本机代码慢。 Java使用JIT编译器来克服此问题。

JIT编译器不能完全替代解释器。执行引擎仍在使用它。但是,JVM根据调用方法的频率使用JIT编译器。

JIT编译器将整个方法的字节码编译为机器本机代码,因此可以直接重用与标准编译器一样,生成中间代码,进行优化,然后生成机器本机代码。

探查器是JIT编译器的特殊组件,负责查找热点。 JVM根据运行时收集的性能分析信息来决定要编译的代码。

Java是编译语言还是解释语言?

这样的效果是,经过几个执行周期,Java程序可以更快地执行其工作。 JVM了解到热点后,便可以创建本机代码,从而使运行速度更快。

6.性能比较

让我们看一下JIT编译如何提高Java的运行时性能。

6.1。斐波那契性能测试

我们将使用一种简单的递归方法来计算第n个斐波那契数:

private static int fibonacci(int index) {

 if (index <= 1) {

 return index;

 }

 return fibonacci(index-1) + fibonacci(index-2);

 }

为了衡量重复方法调用的性能收益,我们将运行Fibonacci方法100次:

for (int i = 0; i < 100; i++) {

 long startTime = System.nanoTime();

 int result = fibonacci(12);

 long totalTime = System.nanoTime() - startTime;

 System.out.println(totalTime);

 }

首先,我们将正常编译并执行Java代码:

$ java Fibonacci.java

然后,我们将在禁用JIT编译器的情况下执行相同的代码:

$ java -Djava.compiler=NONE Fibonacci.java

最后,我们将在C ++和JavaScript中实现并运行相同的算法进行比较。

6.2。性能测试结果

让我们看一下运行Fibonacci递归测试后测得的平均性能(以纳秒为单位):

  • 使用JIT编译器的Java – 2726 ns –最快
  • 没有JIT编译器的Java – 17965 ns –慢559%
  • 没有O2优化的C ++ – 9435 ns –降低246%
  • 具有O2优化的C ++ – 3639 ns –慢33%
  • JavaScript – 22998 ns –慢743%

在此示例中,使用JIT编译器Java的性能提高了500%以上。但是,JIT编译器确实需要运行一些才能运行。

有趣的是,即使在启用O2优化标志的情况下编译C ++,Java的性能也比C ++代码好33%。不出所料,当仍然解释Java时, C ++在前几次运行中的性能要好得多

Java还胜过与Node一起运行的等效JavaScript代码,后者也使用JIT编译器。结果显示性能提高了700%以上。主要原因是Java的JIT编译器启动速度更快

7.要考虑的事情

从技术上讲,可以将任何静态编程语言代码直接编译为机器代码。也可以逐步解释任何编程代码。

与许多其他现代编程语言类似,Java使用编译器和解释器的组合。目标是利用两全其美,实现高性能和平台无关的执行

在本文中,我们重点介绍了HotSpot中的工作方式。 HotSpot是Oracle默认的开源JVM实现。 Graal VM也基于HotSpot,因此适用相同的原理。

如今,最流行的JVM实现使用解释器和JIT编译器组合。但是,其中一些可能使用其他方法。

8.结论

在本文中,我们研究了Java和JVM内部。我们的目标是确定Java是编译语言还是解释语言。我们探索了Java编译器和JVM执行引擎的内部结构。

基于此,我们得出结论, Java使用了两种方法的组合。

我们用Java编写的源代码在构建过程中首先被编译为字节码。然后,JVM解释生成的字节码以供执行。但是,JVM还在运行时使用JIT编译器来提高性能。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *