1.Java平台的理解-JIT

第一讲:

1.Java语言的两大特性

  • 一次编译,到处运行(Compile once,run anywhere),具有跨平台的能力。
  • 垃圾回收(GC,Garbage Collection),Java通过垃圾收集器(Garbage Collection)回收分配内存,程序员不需要操心内存的分配和回收

2.Java开发环境

  • JRE:Java Runtime Enviroment,Java运行时环境,运行Java程序的必需条件,包括Java虚拟机,Java核心类库和支持文件。如果只是运行Java程序,只需要安装JRE就可以了。
  • JDK:Java Development Kit,是完整的Java软件开发包,包含了JRE,编译器和其他的工具(比如:JavaDoc,Java调试器),可以让开发者开发、编译、执行Java应用程序。

3.Java是解释执行的分析

对于“Java是解释执行”这句话,这个说法不太准确。

源文件.Java文件–通过Javac编译–二进制的.class文件(字节码[byte code],与平台无关)–JVM(Java虚拟机)解释器–特定平台机器码[machine code]。

Java的编译器先将其编译为class文件,也就是字节码,这一步称为Javac编译;然后将字节码交由jvm(java虚拟机)解释执行,因而很多地方说“java是一种半编译、半解释执行”的语言。现在由于JIT的出现,这种说法有部分是错误的。

常见的JVM,比如我们大多数情况使用的OracleJDK 提供的HotspotJVM,都提供了JIT(Just-In-Time)编译器,也就是通常所说的动态编译器,JIT能够在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行了。

首先javac编译器将源代码编译成字节码。然后jvm 类加载器加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度相对会比较慢。有些方法和代码块是高频率调用的,也就是所谓的热点代码,所以引进jit技术,
提前将这类字节码直接编译成本地机器码。这样类似于缓存技术,运行时再遇到这类代码直接可以执行,而不是先解释后执行。

在运行时JIT会把翻译过的机器码保存起来,已备下次使用,因此从理论上来说,采用该JIT技术可以,可以接近以前纯编译技术。

上面所说的,不管是解释执行还是编译执行,前提都是Javac编译器将源代码编译成字节码,然后再去判断是否开启JIT。

1.Java平台的理解-JIT

4.知识扩展

对于Java平台的理解,可以从以下很多方面进行概括:

  • Java语言特性,包括泛型、Lambda等语言特性
  • 基础类库:包括集合、IO/NIO、网络、并发、安全等等
  • JVM的一些基础概念和机制
    • 类加载机制:常用版本JDK内嵌的Class-Loader,例如Bootstrap、Application和Extension Class-loader
    • 类加载过程:加载、验证、链接、初始化
    • 垃圾回收的基本原理,最常见的垃圾收集器:Serial GC、Parallel GC、CMS、G1等等
  • JDK包含的工具或者Java领域内的其他工具,如编译器、运行时环境、安全工具、诊断和监控工具。

5.Java跨平台的解析

  • 我们通常把Java分为编译期和运行时。这里说的Java的编译和C/C++是有着不同的意义的,Javac的编译,编译Java源码生成“.class”文件里面实际是字节码,而不是可以直接执行的机器码。Java通过字节码和Java虚拟机(JVM)这种跨平台的抽象,屏蔽了操作系统和硬件的细节,这也是实现“一次编译,到处执行”的基础。
  • 编译后的字节码与平台无关,所以Java所谓的跨平台就是在不同平台上安装了不同的jvm,而在不同平台上生成的.class文件都是一样的,而.class文件再由对应平台的jvm解释成对应平台的机器码执行。它首先将源代码编译成字节码,然后依赖各种不同平台上的虚拟机来解释执行字节码,从而实现了“一次编写,到处运行”的跨平台特性。
  • 在运行时,JVM 会通过类加载器(Class-Loader)加载字节码,解释或者编译执行。就像我前面提到的,主流Java版本中,如JDK8实际是解释和编译混合的一种模式,即所谓的混合模式(-Xmixed)。通常运行在server模式的JVM,会进行上万次调用以收集足够的信息进行高效的编译,client模式这个门限是1500次。Oracle Hotspot JVM 内置了两个不同的JITcompiler,C1对应前面说的client模式,适用于对于启动速度敏感的应用,比如普通Java桌面应用;C2对应server模式,它的优化是为长时间运行的服务器端应用设计的。默认是采用所谓的分层编译(TieredCompilation)。
  • Java虚拟机启动时,可以指定不同的参数对运行模式进行选择。比如,指定“-Xint”,就是告诉JVM 只进行解释执行,不对代码进行编译,这种模式抛弃了JIT可能带来的性能优势。毕竟解释器(interpreter)是逐条读入,逐条解释运行的。与其相对应的,还有一个“-Xcomp”参数,这是告诉JVM 关闭解释器,不要进行解释执行,或者叫作最大优化级别。那你可能会问这种模式是不是最高效啊?简单说,还真未必。“-Xcomp”会导致JVM 启动变慢非常多。
  • 除了我们日常最常见的Java使用模式,其实还有一种新的编译方式,即所谓的AOT(Ahead-of -TimeCompilation),直接将字节码编译成机器代码,这样就避免了JIT预热等各方面的开销,比如Oracle JDK9就引入了实验性的AOT特性,并且增加了新的jaotc工具。
  • 推荐博文 深入理解java虚拟机(十三) Java 即时编译器JIT机制以及编译优化