到底是JDK1.x还是JDKx?
从1.5版本开始, 官方文档的公开版本号开始使用JDKx的命名方式; 但程序员内部使用的开发版本号仍为JDK1.x
JDK
Java技术体系包括:
- Java程序设计语言
- 各种硬件平台上的JVM实现
- Java类库API
- Class的文件格式
- 第三方Java类库
- (Kotlin, Clojure, JRuby, Gloovy等运行于JVM上的语言和相关程序)
其中前2, 3项*JVM, java类库API中的java SE API子集(核心包)构成JRE, 是Java程序运行的标准环境
前三种(Java程序设计语言, JVM, Java类库)构成JDK, 是用于支持Java程序开发的最小环境, 还含有java编译和调试等工具(java, javac, jar等)
Java SE vs Java EE
JavaSE(standard)是面向桌面级应用的java平台, 在JDK6前被称为J2SE
JavaEE(Enterprise)是支持使用多层架构的企业应用的java平台, 在JDK6前被称为J2EE, 相对JavaSE有大量扩充, 通常以javax.*作为包名, 而JavaSE API的核心包以java.*命名(后来也有javax的包进入了JavaSE API核心包中)
J2SE J2EE 的"2"表示这种技术体系的划分是从JDK1.2开始的, JDK6后
JDK8
JDK7开发期间SUN被Oracle收购(有HotSpot虚拟机), Oracle还有从BEA收购的JRocket虚拟机, 原本打算将两个虚拟机合二为一, 但两者架构差别过大, 能融合的太少
JDK8完成了以下功能:
- Lambda表达式(函数式表达)
- Nashorn JavaScript引擎支持
- 新的日期,时间API
- 彻底移除HotSpot永久代, 用metaspace
- ...
- HashMap, concurrent包下的修改
- 方法引用 ::
- 接口可以有默认方法和静态方法
- 可以重复注解, 可注解在任意地方
- Optional解决空指针问题
- Stream类, 对集合数组等, 可以作filter,map,reduce...
JVM参数
标准参数
-开头, 如:
java -version
java -jar
通过java -help可查看所有标准参数
非标准参数
-X开头, 在将来的JVM版本可能变化
用java -X可查看所有非标准参数
-Xms, -Xloggc:路径 等
不稳定参数
-XX, 会引起JVM性能的差异, 因此给JVM带来不稳定性
分为三类:
-
性能参数: 用于性能调优和内存分配
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:NewRatio=2 -XX:SurvivorRatio=8
-
行为参数: 改变JVM的基础行为, 如GC更换算法选择
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
-
调试参数: 监控, 打印输出, jdk11后改为-Xlog
-XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintGCDetails
JVM种类
Classic VM
纯解释器方式执行Java代码/用外挂即时编译器(如sunwjit)完全接管执行
由于需要将整个程序编译, 因此很慢
在JDK1.2为默认JVM, 在JDK1.3为备用JVM
两者不能配合工作
ExactVM
使用准确式内存管理, 即虚拟机可以知道内存中的数据具体是引用类型还是某种基本类型, 因此在垃圾回收时能够知道堆上哪些数据是仍被使用(有引用指向)
HotSpotVM
核心技术是热点代码探测, 能够通过执行计数器找到最具有编译价值的代码, 然后通知即使编译器以方法为单位进行编译.
如果发现一个方法被频繁调用, 或方法中有效循环次数很多, 会分别触发即时编译和栈上替换编译(On-Stack Replacement, OSR)
通过这种编译器和解释器协同, 能够在程序响应时间和执行性能中取得平衡.
JDK1.2开始加入, 1.3后成为默认版本. JDK8后已经融合了JRocket功能
JRocket
全部用即时编译器编译后执行, 无解释器(服务端程序可以启动慢), 执行很快
垃圾收集器和Java Mission Control
现已停止发展
J9
虚拟机的职责分离和模块化优秀
已经开源为OpenJ9
LiquidVM
同由BEA开发, 也被称为JRocketVE(virtual edition)
虚拟机能够越过操作系统直接控制硬件, 比如不需要内核态/用户态切换, 可最大程度地发挥硬件的能力
GraalVM
无语言化
将各种语言的源代码或源代码编译后的中间格式, 通过解释器转换为能够被GraalVM接收的中间格式
做到指令集仅与机器特性相关, 不与语言特性相关
在HotSpot基础上诞生, 因此可作为一个完整的javaSE8的虚拟机使用
即时编译器
即时编译即在运行时将代码编译为物理硬件可直接执行的机器码
Hotspot有两个即时编译器, 通常用分层编译机制与解释器配合
C1
编译耗时短但输出代码优化程度低的客户端编译器
C2
编译耗时长但输出代码优化质量更高的服务端编译器
Graal
自JDK10加入, 可替代C2
可用-XX:+... 参数来开启
提前编译器
预编译为二进制库, 运行时可直接调用
微服务: 单个微服务所需的内存很小, 需要经常启动, 暂停, 更新
HotSpot本身就有几十MB大小,
需要为不同硬件, 操作系统编译对应的发行包
SubstrateVM
是GraalVM里的一个极小型运行时环境