You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

69 lines
8.3 KiB
Markdown

2 years ago
# 第1讲 | 谈谈你对Java平台的理解
从你接触Java开发到现在你对Java最直观的印象是什么呢是它宣传的 “Write once, run anywhere”还是目前看已经有些过于形式主义的语法呢你对于Java平台到底了解到什么程度请你先停下来总结思考一下。
今天我要问你的问题是谈谈你对Java平台的理解“Java是解释执行”这句话正确吗
## 典型回答
Java本身是一种面向对象的语言最显著的特性有两个方面一是所谓的“**书写一次,到处运行**”Write once, run anywhere能够非常容易地获得跨平台能力另外就是**垃圾收集**GC, Garbage CollectionJava通过垃圾收集器Garbage Collector回收分配内存大部分情况下程序员不需要自己操心内存的分配和回收。
我们日常会接触到JREJava Runtime Environment或者JDKJava Development Kit。 JRE也就是Java运行环境包含了JVM和Java类库以及一些模块等。而JDK可以看作是JRE的一个超集提供了更多工具比如编译器、各种诊断工具等。
对于“Java是解释执行”这句话这个说法不太准确。我们开发的Java的源代码首先通过Javac编译成为字节码bytecode然后在运行时通过 Java虚拟机JVM内嵌的解释器将字节码转换成为最终的机器码。但是常见的JVM比如我们大多数情况使用的Oracle JDK提供的Hotspot JVM都提供了JITJust-In-Time编译器也就是通常所说的动态编译器JIT能够在运行时将热点代码编译成机器码这种情况下部分热点代码就属于**编译执行**,而不是解释执行了。
## 考点分析
其实这个问题问得有点笼统。题目本身是非常开放的往往考察的是多个方面比如基础知识理解是否很清楚是否掌握Java平台主要模块和运行原理等。很多面试者会在这种问题上吃亏稍微紧张了一下不知道从何说起就给出个很简略的回答。
对于这类笼统的问题,你需要尽量**表现出自己的思维深入并系统化Java知识理解得也比较全面**,一定要避免让面试官觉得你是个“知其然不知其所以然”的人。毕竟明白基本组成和机制,是日常工作中进行问题诊断或者性能调优等很多事情的基础,相信没有招聘方会不喜欢“热爱学习和思考”的面试者。
即使感觉自己的回答不是非常完善,也不用担心。我个人觉得这种笼统的问题,有时候回答得稍微片面也很正常,大多数有经验的面试官,不会因为一道题就对面试者轻易地下结论。通常会尽量引导面试者,把他的真实水平展现出来,这种问题就是做个开场热身,面试官经常会根据你的回答扩展相关问题。
## 知识扩展
回归正题对于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领域内其他工具等如编译器、运行时环境、安全工具、诊断和监控工具等。这些基本工具是日常工作效率的保证对于我们工作在其他语言平台上同样有所帮助很多都是触类旁通的。
下图是我总结的一个相对宽泛的蓝图供你参考。
![](https://static001.geekbang.org/resource/image/20/32/20bc6a900fc0b829c2f0e723df050732.png)
不再扩展了,回到前面问到的解释执行和编译执行的问题。有些面试官喜欢在特定问题上“刨根问底儿”,因为这是进一步了解面试者对知识掌握程度的有效方法,我稍微深入探讨一下。
众所周知我们通常把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 compilerC1对应前面说的client模式适用于对于启动速度敏感的应用比如普通Java桌面应用C2对应server模式它的优化是为长时间运行的服务器端应用设计的。默认是采用所谓的分层编译TieredCompilation。这里不再展开更多JIT的细节没必要一下子就钻进去我会在后面介绍分层编译的内容。
Java虚拟机启动时可以指定不同的参数对运行模式进行选择。 比如,指定“-Xint”就是告诉JVM只进行解释执行不对代码进行编译这种模式抛弃了JIT可能带来的性能优势。毕竟解释器interpreter是逐条读入逐条解释运行的。与其相对应的还有一个“-Xcomp”参数这是告诉JVM关闭解释器不要进行解释执行或者叫作最大优化级别。那你可能会问这种模式是不是最高效啊简单说还真未必。“-Xcomp”会导致JVM启动变慢非常多同时有些JIT编译器优化方式比如分支预测如果不进行profiling往往并不能进行有效优化。
除了我们日常最常见的Java使用模式其实还有一种新的编译方式即所谓的AOTAhead-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](http://openjdk.java.net/jeps/295)。AOT也不仅仅是只有这一种方式业界早就有第三方工具如GCJ、Excelsior JET提供相关功能。
另外JVM作为一个强大的平台不仅仅只有Java语言可以运行在JVM上本质上合规的字节码都可以运行Java语言自身也为此提供了便利我们可以看到类似Clojure、Scala、Groovy、JRuby、Jython等大量JVM语言活跃在不同的场景。
今天我简单介绍了一下Java平台相关的一些内容目的是提纲挈领地构建一个整体的印象包括Java语言特性、 核心类库与常用第三方类库、Java虚拟机基本原理和相关工具希望对你有所帮助。
## 一课一练
关于今天我们讨论的题目你做到心中有数了吗知道不如做到请你也在留言区写写自己对Java平台的理解。我会选出经过认真思考的留言送给你一份学习鼓励金欢迎你与我一起讨论。
你的朋友是不是也在准备面试呢?你可以“请朋友读”,把今天的题目分享给好友,或许你能帮到他。