第1讲 | 对Java平台的理解

(注意 :"下划线字体" 会有在Java Core Tec - Detail 模块有详细解释)

------------------------------------问答---------------------------------------------

一 、谈谈你对 Java 平台的理解?“Java 是解释执行”,这句话正确吗?

1.Java 本身是一种面向对象的语言,最显著的特性有两个方面:

  • 1.1 “书写一次,到处运行”(Write once, run anywhere),能够非常容易地获得跨平台能力。
  •         > Java的跨平台特性与Java虚拟机的存在密不可分,Windows平台和Linux平台都有相应的JDK(JDK包含了JVM),安装好JDK后也就有了Java语言的运行环境。
  •         > 其实Java语言本身与其他的编程语言没有特别大的差异,并不是说Java语言可以跨平台,而是在不同的平台都有可以让Java语言运行的环境而已,所以才有了Java一次编译,到处运行这样的效果。
  •         > 程序从源代码到运行的三个阶段:编码——编译——运行。Java在编译阶段则体现了跨平台的特点。编译过程大概是这样的:首先是Javac 将Java源代码转化成.CLASS文件字节码,这是第一次编译。.CLASS文件就是可以到处运行的文件。然后Java字节码会被转化为目标机器代码,这是是由JVM来执行的,即Java的第二次编译。
  •         >其实,不同的平台,可执行的机器码必然是不一样的。源代码自然需要依据不同的平台分别被编译。相对于Java,  C 语言程序经常需要调用操作系统层面的 API。不同的操作系统,API 一般不同。为了支持多平台,C 语言程序的源文件需要根据不同平台修改多次。这应该是一个非常大的痛点。
  • 1.2 另外就是垃圾收集(GC, Garbage Collection),Java 通过垃圾收集器(Garbage Collector)回收分配内存,大部分情况下,程序员不需要自己操心内存的分配和回收。
   其他基本的概念:
  • 1.3  JRE(Java Runtime Environment),也就是 Java 运行环境,包含了 JVM 和 Java 类库,以及一些模块等。
  • 1.4 JDK (Java Development Kit),可以看作是 JRE 的一个超集,提供了更多工具,比如编译器、各种诊断工具等。

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

  • 2.1 我们开发的 Java 的源代码,首先通过 Javac 编译成为字节码(bytecode) 
  • 2.2 然后,在运行时,通过 Java 虚拟机(JVM)内嵌的解释器将字节码转换成为最终的机器码。
  • 2.3 但是常见的 JVM,比如我们大多数情况使用的 Oracle JDK 提供的 Hotspot JVM,都提供了 JIT(Just-In-Time)编译器,也就是通常所说的动态编译器,JIT 能够在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行了。

------------------------------------扩展---------------------------------------------

二、 Java Overview Image

1. Java 语言特性

  • 面向对象(封装,继承,多态)
  • 平台无关性(JVM运行.class文件)
  • 语言(反射泛型,Lambda)
  • 类库(集合,并发,网络,IO/NIO)
  • JRE(Java运行环境,JVM,类库)
  • JDK(Java开发工具,包括JRE,javac,诊断工具)

2. JVM基础概念和机制

  • 类加载机制
  • 常用版本 JDK(如 JDK 8)内嵌的 Class-Loader,例如 Bootstrap、 Application 和 Extension Class-loader
  • 类加载大致过程:加载、验证、链接、初始化(这里参考了周志明的《深入理解 Java 虚拟机》,非常棒的 JVM 上手书籍)
  • 自定义 Class-Loader 

3. 垃圾收集

  • 最常见的垃圾收集器,SerialGC、Parallel GC、 CMS、 G1 等,
  • 各个GC适用于什么样的工作负载

4. JDK 包含哪些工具

  • 编译器
  • 运行时环境
  • 安全工具
  • 诊断
  • 监控工具



三、解释执行 & 编译执行

1.通常把 Java 分为编译期和运行时(这里说的 Java 的编译和 C/C++ 是有着不同的意义的):

  • 编译期:Javac 的编译,编译 Java 源码生成“.class”文件里面实际是字节码,而不是可以直接执行的机器码。Java 通过字节码和 Java 虚拟机(JVM)这种跨平台的抽象,屏蔽了操作系统和硬件的细节,这也是实现“一次编译,到处执行”的基础。
  •  运行时: 在运行时,JVM 会通过类加载器(Class-Loader)加载字节码,解释或者编译执行。主流 Java 版本中,如 JDK 8 实际是解释和编译混合的一种模式,即所谓的混合模式(-Xmixed)。

2. Oracle Hotspot JVM 内置了两个不同的 JIT compiler。client 模式 和 server 模式

  • client 模式 : C1模式, 适用于对于启动速度敏感的应用,比如普通 Java 桌面应用。运行在 client模式的 JVM, 最多进行1500次的调用。
  • server模式 : C2模式,它的优化是为长时间运行的服务器端应用设计的。默认是采用所谓的分层编译(TieredCompilation)。运行在 server 模式的 JVM,会进行上万次调用以收集足够的信息进行高效的编译。

3. JVM 参数。Java 虚拟机启动时,可以指定不同的参数对运行模式进行选择:

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

4. 新的编译方式 AOT(Ahead-of-Time Compilation)

  • AOT 直接将字节码编译成机器代码,这样就避免了 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)提供相关功能。





猜你喜欢

转载自blog.csdn.net/u011144776/article/details/80608868