>[info] 平台无关性:一次编译,到处运行
>[] 我对『Compile once, run anywhere』这个宣传语提出的历史背景非常感兴趣。这个宣传语似乎在暗示 C 语言有一个缺点:对于每一个不同的平台,源代码都要被编译一次。我不解的地方是,为什么这会是一个问题?不同的平台,可执行的机器码必然是不一样的。源代码自然需要依据不同的平台分别被编译。 我觉得真正问题不在编译这一块,而是在 C 语言源文件这一块。我没有 C 语言的编程经验,但是似乎 C 语言程序经常需要调用操作系统层面的 API。不同的操作系统,API 一般不同。为了支持多平台,C 语言程序的源文件需要根据不同平台修改多次。这应该是一个非常大的痛点。我回头查了一下当时的宣传语,原文是『Write once, run anywhere』,焦点似乎并不在编译上,而是在对源文件的修改上。
>[warning] GC:垃圾回收机制
>[success] 语言特性:泛型、反射、`lamuda`表达式表达式
>[danger]面向对象:封装、继承、多态
>[info]类库:集合、并发、网络、`IO/NIO`
>[success] Jva半编译半解释机制
>[] 众所周知,我们通常把`Java`分为编译期和运行时。这里说的`Java`的编译和`C/C++`是有着不同的意义的,`Javac`的编译,编译`Java`源码生成`“.class”`文件里面实际是字节码,而不是可以直接执行的机器码。`Java`通过字节码和`Java`虚拟机`(JVM)`这种跨平台的抽象,屏蔽了操作系统和硬件的细节,这也是实现“一次编译,到处执行”的基础。
在运行时,`JVM`会通过类加载器`(Class-Loader)`加载字节码,解释或者编译执行。就像我前面提到的,主流`Java`版本中,如`JDK 8`实际是解释和编译混合的一种模式,即所谓的混合模式`(\-Xmixed)`。通常运行在`server`模式的`JVM`,会进行上万次调用以收集足够的信息进行高效的编译,`client`模式这个门限是1500次。`Oracle Hotspot JVM`内置了两个不同的`JIT compiler`,`C1`对应前面说的`client`模式,适用于对于启动速度敏感的应用,比如普通`Java`桌面应用;`C2`对应`server`模式,它的优化是为长时间运行的服务器端应用设计的。
默认是采用所谓的分层编译`(TieredCompilation)`。这里不再展开更多`JIT`的细节,没必要一下子就钻进去,我会在后面介绍分层编译的内容。
Java虚拟机启动时,可以指定不同的参数对运行模式进行选择。 比如,指定`“-Xint”`,就是告诉`JVM`只进行解释执行,不对代码进行编译,这种模式抛弃了`JIT`可能带来的性能优势。
毕竟解释器`(interpreter)`是逐条读入,逐条解释运行的。与其相对应的,还有一个`“-Xcomp”`参数,这是告诉`JVM`关闭解释器,不要进行解释执行,或者叫作最大优化级别。那你可能会问这种模式是不是最高效啊?简单说,还真未必。`“-Xcomp”`会导致`JVM`启动变慢非常多,同时有些`JIT`编译器优化方式,比如分支预测,如果不进行`profling`,往往并不能进行有效优化。
除了我们日常最常见的`Java`使用模式,其实还有一种新的编译方式,即所谓的`AOT(Ahead-of-Time Compilation)`,直接将字节码编译成机器代码,这样就避免了`JIT`预热等各方面的开销,比如`Oracle JDK 9`就引入了实验性的`AOT`特性,并且增加了新的`jaotc`工具。利用下面的命令把某个类或者某个模块编译成为`AOT`库。
`jaotc --output libHelloWorld.so HelloWorld.class`
`jaotc --output libjava.base.so --module java.base`
然后,在启动时直接指定就可以了。
`java -XX:AOTLibrary=./libHelloWorld.so,./libjava.base.so HelloWorld`
而且,`Oracle JDK`支持分层编译和`AOT`协作使用,这两者并不是二选一的关系。如果你有兴趣,可以参考相关文档:http://openjdk.java.net/jeps/295。`AOT`也不仅仅是只有这一种方式,业界早就有第三方工具(如`GCJ、Excelsior JET`)提供相关功能。
另外,`JVM`作为一个强大的平台,不仅仅只有`Java`语言可以运行在`JVM`上,本质上合规的字节码都可以运行,`Java`语言自身也为此提供了便利,我们可以看到类似`Clojure`、`Scala`、`Groovy`、`JRuby`、`Jython`等大量`JVM`语言,活跃在不同的场景。