从业近一年时间了,发现我对Java的理解仅仅限于跨平台,不需要自己管理堆内存,面向对象这些浅显的概念,平时也看过一些关于Java平台的解释,一些名词会在脑海中出现,但是具体含义自己也说不清楚。比如JIT,双亲委派等等。
记录一下从今天起记录一下自己学习过的知识。
什么是Java平台,还记得18年校招面试官问我如果现在让你学习Java,你会怎么学习?
- 学习Java的面向对象模型,因为Java不同于C++还保留面向过程的特性,所有的代码都必须写在类里面
- 学习Java的内存管理,因为Java不同于C++,C++程序员需要自己管理申请的堆空间内存。
这是当时我的回答,发现过去一年多了,让我回答这个问题可能答案也差不多。
那么,什么Java平台?
Java 本身是一种面向对象的语言,最显著的特性有两个方面,一是所谓的“书写一次,到处运行”(Write once, run anywhere),能够非常容易地获得跨平台能力;另外就是垃圾收集(GC, Garbage Collection),Java 通过垃圾收集器(Garbage Collector)回收分配内存,大部分情况下,程序员不需要自己操心内存的分配和回收。
如果并不需要开发Java程序,只需要安装JRE(Java Runtime Environment)就可以运行Java程序了,JDK是JRE的一个超集,它还有编译器、诊断工具等。
以上是对Java的一些简单了解,也是目前我对Java平台的了解。
众所周知,我们通常把 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)。Java 虚拟机启动时,可以指定不同的参数对运行模式进行选择。 比如,指定“-Xint”,就是告诉 JVM 只进行解释执行,不对代码进行编译,这种模式抛弃了 JIT 可能带来的性能优势。毕竟解释器(interpreter)是逐条读入,逐条解释运行的。与其相对应的,还有一个“-Xcomp”参数,这是告诉 JVM 关闭解释器,不要进行解释执行,或者叫作最大优化级别。那你可能会问这种模式是不是最高效啊?简单说,还真未必。“-Xcomp”会导致 JVM 启动变慢非常多,同时有些 JIT 编译器优化方式,比如分支预测,如果不进行 profiling,往往并不能进行有效优化。除了我们日常最常见的 Java 使用模式,其实还有一种新的编译方式,即所谓的 AOT(Ahead-of-Time Compilation),直接将字节码编译成机器代码,这样就避免了 JIT 预热等各方面的开销,比如 Oracle JDK 9 就引入了实验性的 AOT 特性,并且增加了新的 jaotc 工具。利用
另外,JVM 作为一个强大的平台,不仅仅只有 Java 语言可以运行在 JVM 上,本质上合规的字节码都可以运行,Java 语言自身也为此提供了便利,我们可以看到类似 Clojure、Scala、Groovy、JRuby、Jython 等大量 JVM 语言,活跃在不同的场景。
一些理解
Java特性
- 面向对象(封装,继承,多态)
- 平台无关性(JVM运行.class文件)
- 语言(泛型,Lambda)
- 类库(集合,并发,网络,IO/NIO)
- JRE(Java运行环境,JVM,类库)
- JDK(Java开发工具,包括JRE,javac,诊断工具)
Java是解析运行吗?不是的
- Java源代码经过Javac编译成.class文件
- .class文件经JVM解析或编译运行。
- 解析:.class文件经过JVM内嵌的解析器解析执行。
- 编译:存在JIT编译器(Just In Time Compile 即时编译器)把经常运行的代码作为"热点代码"编译与本地平台相关的机器码,并进行各种层次的优化。
- AOT编译器: Java 9提供的直接将所有代码编译成机器码执行。
java程序执行步骤:
第一步javac编译器将源代码编译成字节码。第二部jvm类加载器加载字节码文件,第三步通过解释器逐行解释执行。
第三部也是我们常说的解释执行,如果只有这种方式,代码执行的效率会比较低。有些方法和代码块是高频率调用的,也就是所谓的热点代码,所以引进Jit技术,提前将这类字节码直接编译成本地机器码(这些步骤发生在Java程序启动过程中,不同于AOT它是直接将字节码编译成机器码)。这样类似于缓存技术,运行时再遇到这类代码直接可以执行,而不是先解释后执行。