Java是什么
Java是一种高级的面向对象的程序设计语言 。
Java的特性
- 面向对象(封装,继承,多态)
- 平台无关性(JVM运行.class文件)
- 语言(泛型,Lambda)
- 类库(集合,并发,网络,IO/NIO)
- JRE(Java运行环境,JVM,类库)
- JDK(Java开发工具,包括JRE,javac,诊断工具)
Java是解释执行,这句话正确吗?
Java本身是一种面向对象的语言,最显著的特性有两个方面,一是所谓的“一次编译,到处执行”(Compile once, run anywhere),能够非常容易地获得跨平台能力;另外就是垃圾收集(GC, Garbage Collection),Java通过垃圾收集器(Garbage Collector)回收分配内存,大部分情况下,程序员不需要自己操心内存的分配和回收。
一次编译、到处运行”说的是Java语言跨平台的特性,Java的跨平台特性与Java虚拟机的存在密不可分,可在不同的环境中运行。比如说Windows平台和Linux平台都有相应的JDK,安装好JDK后也就有了Java语言的运行环境。其实Java语言本身与其他的编程语言没有特别大的差异,并不是说Java语言可以跨平台,而是在不同的平台都有可以让Java语言运行的环境而已,所以才有了Java一次编译,到处运行这样的效果。 严格的讲,跨平台的语言不止Java一种,但Java是较为成熟的一种。“一次编译,到处运行”这种效果跟编译器有关。编程语言的处理需要编译器和解释器。Java虚拟机和DOS类似,相当于一个供程序运行的平台。 程序从源代码到运行的三个阶段:编码——编译——运行——调试。Java在编译阶段则体现了跨平台的特点。编译过程大概是这样的:首先是将Java源代码转化成.CLASS文件字节码,这是第一次编译。.class文件就是可以到处运行的文件。然后Java字节码会被转化为目标机器代码,这是是由JVM来执行的,即Java的第二次编译。 “到处运行”的关键和前提就是JVM。因为在第二次编译中JVM起着关键作用。在可以运行Java虚拟机的地方都内含着一个JVM操作系统。从而使JAVA提供了各种不同平台上的虚拟机制,因此实现了“到处运行”的效果。需要强调的一点是,java并不是编译机制,而是解释机制。Java字节码的设计充分考虑了JIT这一即时编译方式,可以将字节码直接转化成高性能的本地机器码,这同样是虚拟机的一个构成部分。
我们日常会接触到 JRE(Java Runtime Environment)或者 JDK(Java Development Kit)。 JRE,也就是 Java运行环境,包含了 JVM和 Java类库,以及一些模块等。而 JDK可以看作是 JRE的一个超集,提供了更多工具,比如编译器、各种诊断工具等。 对于“Java是解释执行”这句话,这个说法不太准确。我们开发的 Java的源代码,首先通过 Javac编译成为字节码(bytecode),然后,在运行时,通过 Java虚拟机(JVM)内嵌的解释器将字节码转换成为最终的机器码。但是常见的 JVM,比如我们大多数情况使用的 Oracle JDK提供的 Hospot JVM,都提供了 JIT(Just-In-Time)编译器,也就是通常所说的动态编译器,JIT能够在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行了。
JVM(Java Virtual Machine)
-
什么是JVM?
(JVM)Java Virtual Machine,是Java程序跨平台的关键,不同的平台有不同的JVM,而java字节码不包含任何与平台相关的信息,不直接与平台交互,而是通过JVM间接与平台交互。应用程序在执行时,JVM加载字节码,将字节码解释成特定平台的机器码,让平台执行。众所周知,我们通常把 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使用模式,其实还有一种新的编译方式,即所谓的 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协作使用,这两者并不是二选一的关系。如果你有兴趣,可以参考相关文档:openjdk.java.net/jeps/295。AOT也不仅仅是只有这一种方式,业界早就有第三方工具(如 GCJ、Excelsior JET)提供相关功能。
另外,JVM作为一个强大的平台,不仅仅只有 Java语言可以运行在 JVM上,本质上合规的字节码都可以运行,Java语言自身也为此提供了便利,我们可以看到类似 Clojure、Scala、Groovy、JRuby、Jython等大量 JVM语言,活跃在不同的场景。
扩展
对于 Java 平台的理解,可以从很多方面简明扼要地谈一下,例如:Java 语言特性,包括泛型、Lambda 等语言特性;基础类库,包括集合、IO/NIO、网络、并发、安全等基础类库。对于我们日常工作应用较多的类库,面试前可以系统化总结一下,有助于临场发挥。
或者谈谈 JVM 的一些基础概念和机制,比如 Java 的类加载机制,常用版本 JDK(如 JDK 8)内嵌的 Class-Loader,例如 Bootstrap、 Application 和 Extension Class-loader;类加载大致过程:加载、验证、链接、初始化(这里参考了周志明的《深入理解 Java 虚拟机》,非常棒的 JVM 上手书籍);自定义 Class-Loader 等。还有垃圾收集的基本原理,最常见的垃圾收集器,如 SerialGC、Parallel GC、 CMS、 G1 等,对于适用于什么样的工作负载最好也心里有数。这些都是可以扩展开的领域,我会在后面的专栏对此进行更系统的介绍。
当然还有 JDK 包含哪些工具或者 Java 领域内其他工具等,如编译器、运行时环境、安全工具、诊断和监控工具等。这些基本工具是日常工作效率的保证,对于我们工作在其他语言平台上,同样有所帮助,很多都是触类旁通的。
下图是总结的一个相对宽泛的蓝图供大家参考

补充!
微观角度: Java平台中有两大核心:
- Java语言本身、JDK中所提供的核心类库和相关工具
- Java虚拟机以及其他包含的GC
Java语言本身、JDK中所提供的核心类库和相关工具 从事Java平台的开发,掌握Java语言、核心类库以及相关工具是必须的,我觉得这是基础中的基础。 对语言本身的了解,需要开发者非常熟悉语言的语法结构;而Java又是一种面对对象的语言,这又需要开发者深入了解面对对象的设计理念; Java核心类库包含集合类、线程相关类、IO、NIO、J.U.C并发包等; JDK提供的工具包含:基本的编译工具、虚拟机性能检测相关工具等。
- 大部分情况下,编程者只需要关心Java语言本身,而无需特意关心底层细节。包括对内存的分配和回收,也全权交给了GC。
- 对于虚拟机而言,只要是符合规范的字节码,它们都能被加载执行,当然,能正常运行的程序光满足这点是不行的,程序本身需要保证在运行时不出现异常。所以,Scala、Kotlin、Jython等语言也可以跑在虚拟机上。
本文总结出自极客时间的『Java核心技术36讲』