深入理解JVM-笔记1-引入

416 阅读4分钟

到底是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里的一个极小型运行时环境