谈谈你对java平台的理解

从你接触 Java 开发到现在,你对 Java 最直观的印象是什么呢?是它宣传的 “Complier once, run anywhere”,还是目前看已经有些过于形式主义的语法呢?你对于 Java 平台到底了解到什么程度?请你先停下来总结思考一下。

今天的问题是:谈谈你对java的理解,java是“解释执行”这句话对吗?

先科普下什么是“解释执行”? 什么是“编译执行”?

  • 解释执行
    解释执行时高级语言翻译程序的一种方式,它将源语言(如VASIC)书写的源程序作为输入,解释一句后就提交给计算机执行一句,并不生成目标程序。这种方式很适合终端与人的交互,在终端输入一个命令,解释程序立即将该命令解释成一条或者多条计算机指令提交硬件执行计算,并将计算结果返回终端。这的确很方便,但是执行效率也会很低,假如源程序中有循环,解释程序也不断的提交这段循环代码,造成不必要的浪费。

  • 编译执行
    先将源代码编译成目标语言(如:计算机语言)之后通过连接程序生成目标程序进行执行。

    这是一类很重要的语言处理程序,它把高级语言(如Pascal、C等)源程序作为输入,进行翻译转换,产生出机器语言的目标程序,然后再让计算机去执行这个目标程序,得到计算结果。

典型的回答

java是一门面向对象的编程语言,它有两个非常显著的特征:1. Compile once, run anywhere,能够很容易的获得跨平台的能力。2.提供垃圾收集器,java提供垃圾收集器回收分配内存,大部分情况下程序员不需要关注内存分配问题。

我们日常会接触到JDK或者JRE,JRE是java的运行时环境,包含了java类库和jvm。JDK则是JRE的一个超集,提供了更多的工具,比如编译工具,诊断工具等。

对于java是解释执行的,这种说法不太准确。我们开发的java源代码,首先经过javac编译成字节码,然后通过java虚拟机(JVM)内嵌的解释器解释成机器码。但是常见的JVM,如常用的Oracle JDK提供的Hotspot JVM内部都提供了 JIT(Just-In-Time)编译器,也就是通常所说的动态编译器,JIT 能够在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行了。

什么是JIT?

在部分的商用虚拟机中,Java 程序最初是通过解释器( Interpreter )进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁的时候,就会把这些代码认定为“热点代码”。为了提高热点代码的执行效率,在运行时,即时编译器(Just In Time Compiler )会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化。

解释器和编译器各有各的优点:

解释器优点:当程序需要迅速启动的时候,解释器可以首先发挥作用,省去了编译的时间,立即执行。解释执行占用更小的内存空间。同时,当编译器进行的激进优化失败的时候,还可以进行逆优化来恢复到解释执行的状态。

解释器优点:在程序运行时,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获得更高的执行效率。

因此,整个虚拟机执行架构中,解释器与编译器经常配合工作,如下图所示。
谈谈你对java平台的理解
我们通常把Java分为编译器和运行时。java 的编译和c/c++不同。java的编译时把java源码文件编译成.clss的字节码文件,并不是机器可执行的机器码。Java 通过字节码和 Java 虚拟机(JVM)这种跨平台的抽象,屏蔽了操作系统和硬件的细节,这也是实现“一次编译,到处执行”的基础。

在运行时,JVM是用类加载器加载字节码(.class)解释或者编译执行。主流 Java 版本中,如 JDK 8 实际是解释和编译混合的一种模式,即所谓的混合模式(-Xmixed)

通常在Server模式的JVM,会进行上万次的调用以收集足够的信息进行高效的编译,Client模式下为1500次

Java 虚拟机启动时,可以指定不同的参数对运行模式进行选择。 比如,指定“-Xint”,就是告诉 JVM 只进行解释执行,不对代码进行编译,这种模式抛弃了 JIT 可能带来的性能优势。毕竟解释器(interpreter)是逐条读入,逐条解释运行的。与其相对应的,还有一个“-Xcomp”参数,这是告诉 JVM 关闭解释器,不要进行解释执行,或者叫作最大优化级别。那你可能会问这种模式是不是最高效啊?简单说,还真未必。“-Xcomp”会导致 JVM 启动变慢非常多,同时有些 JIT 编译器优化方式,比如分支预测,如果不进行 profiling,往往并不能进行有效优化。

拓展回答

可参考下图进行拓展谈谈你对java平台的理解