HotSpot

背景 OpenJDK 发行版里默认的 Java 虚拟机实现是 HotSpot(C++)。你安装的 java 命令、容器里的 JDK 镜像,除非明确换用 OpenJ9 或 GraalVM Native Image,否则跑的就是 HotSpot。 Java 领域还有哪些 JVM,见 Java 虚拟机。 HotSpot 是什么 HotSpot 得名于 热点探测(hot spot detection):大部分时间只执行少量代码,JIT 优先编译这些热点方法。内置 解释器、C1 与 C2 两个 JIT 编译器,默认通过 分层编译 在启动速度与峰值性能之间折中。 对比 HotSpot Eclipse OpenJ9 GraalVM Native Image 典型形态 OpenJDK 默认 java IBM Semeru native-image 产物 JIT C1 + C2 自有 JIT 构建期 AOT,无运行时 JIT 常用诊断 jcmd、JFR、Attach 自有工具 与传统 JVM 排障不同 历史 HotSpot 的技术 lineage 来自 Self / Strongtalk 一脉的动态编译与热点探测。Longview Technologies(对外也称 Animorphic)1994 年成立,1997 年 2 月被 Sun 收购;收购后 Sun 在其 VM 技术上为 Java 编写更强的 JIT(C2 等),因运行时持续探测并优化热点代码而得名 HotSpot。 ...

Created 31316-05-31 · Updated 16166-07-16 · 3 min · 507 words · -

HotSpot JIT 编译器(C1/C2)

背景 OpenJDK 默认的 HotSpot 虚拟机通过 解释器 + 即时编译(JIT) 执行字节码:冷代码先解释运行,热点方法再编译为本地机器码。本文归纳 C1/C2 分工、分层编译与热点探测;JDK 21 之后的 AOT 预热见 JDK 25 变更汇总。 C1 与 C2 HotSpot 内置两个 JIT 编译器,历史上也称 Client 编译器 与 Server 编译器,对应 C1 与 C2: 编译器 特点 C1 编译快,做简单、可靠的优化 C2 编译慢,做更重的优化,会依据运行时 profile 做激进优化 二者都只编译 热点代码(多次调用的方法,或多次执行的循环体),编译前须先做热点探测。 Client/Server 两套 VM 的划分在 64 位 JDK 上已基本消失:现代 HotSpot 统一走 Server VM,并通过 分层编译 把 C1 的快速启动与 C2 的峰值性能结合起来(见下一节)。 分层编译(Tiered Compilation) 自 Java 7 起,Server VM 默认启用 分层编译(-XX:+TieredCompilation,一般无需手动开)。HotSpot 用 5 个执行级别 在解释器与两个编译器之间过渡: ...

Created 30306-03-30 · Updated 16166-07-16 · 2 min · 354 words · -

Java 虚拟机

背景 日常说的「JVM」常混用两层含义: JVM 规范(JLS/JVMS):字节码、class 文件格式、类加载语义、JNI、JPDA 等,与具体实现无关。 JVM 实现:真正把字节码跑起来的运行时,如 HotSpot、OpenJ9。 安装 java 命令得到的是 JDK 发行版(见 OpenJDK JDK 发行版;安装命令见 openjdk),其中默认捆绑的虚拟机实现几乎都是 HotSpot。本文介绍 JVM 实现(HotSpot、OpenJ9、GraalVM Native 等)的差异与选型;HotSpot 的参数与工具见 hotspot。 JDK 发行版 vs JVM 实现 Temurin、Corretto、Dragonwell 等是不同厂商打包的 OpenJDK 发行版,默认都跑 HotSpot,不是三种并列的 JVM。换 Temurin 换 Corretto,通常只是换构建源与支持方;要换虚拟机实现才看 OpenJ9(Semeru)或 GraalVM Native Image。发行版对照见 openjdk-distributions.md。 规范层:各实现共同遵守什么 无论用哪种 JVM,下列概念在规范层是共通的: 概念 说明 字节码 javac 产出 .class,由虚拟机解释或 JIT 编译后执行 类加载 加载、链接、初始化;双亲委托等模型见 classloader JNI Java 与本地代码互操作规范,见 java-jni JPDA 调试体系(JDI / JDWP / JVMTI),见 java-debug-JPDA 规范 不 规定用哪种垃圾收集器、有哪些 -XX 开关、是否提供 JFR——这些是实现细节。 主流 JVM 实现对照 实现 典型发行版 特点 适用场景 HotSpot Oracle JDK、Temurin、Corretto、Dragonwell 等 生态最全;C1/C2 JIT、G1/ZGC/Shenandoah、JFR、jcmd、Attach 默认可用 默认首选;绝大多数服务端与桌面应用 Eclipse OpenJ9 IBM Semeru 常更低内存占用、较快启动;工具链与 HotSpot 不同 容器密度高、内存敏感;需验证 agent/诊断工具兼容性 GraalVM GraalVM CE/EE 可嵌 HotSpot 作 JIT 运行时,或通过 Native Image AOT 为本地可执行文件 极致冷启动(serverless、CLI);见 GraalVM 简介、Native Image JRockit 已停止独立发展 曾用于金融低延迟;特性已并入 HotSpot 仅作历史了解,见 jrockit ┌─────────────────────────────────┐ │ Java 语言 + JVM 规范 │ └─────────────────────────────────┘ │ ┌───────────────────────────┼───────────────────────────┐ ▼ ▼ ▼ OpenJDK HotSpot Eclipse OpenJ9 GraalVM (默认 java 命令) (Semeru 等) ┌──────┴──────┐ │ │ ▼ ▼ │ │ HotSpot 运行时 Native Image ▼ ▼ (JIT) (AOT 本地二进制) jcmd / JFR / Attach 自有诊断工具 选型建议 没有明确理由时,用 HotSpot(即常见 OpenJDK 发行版)。文档、agent、APM、排障经验都围绕它积累最多。 内存或启动是瓶颈,且已验证依赖(Attach、部分 agent、GC 日志格式)在目标环境可用,可评估 OpenJ9。 冷启动极敏感(函数计算、短生命周期进程),评估 GraalVM Native Image(见 GraalVM 简介、Native Image);需接受构建期分析、反射配置、动态类加载受限等成本。 不要混用概念:GraalVM 不等于「又一个 HotSpot」;Native Image 路径下没有传统 JIT 预热,也没有完整的 -XX 调优空间。 HotSpot 执行路径(概念) HotSpot 的典型路径(细节见专文): ...

Created 19196-05-19 · Updated 15156-07-15 · 2 min · 308 words · -

HotSpot JVM 启动参数

背景 本文汇总 OpenJDK HotSpot 常用启动参数(-、-X、-XX)。这些开关 不是 JVM 规范的一部分,其他实现(OpenJ9 等)名称与语义可能不同。 JVM 生态选型见 jvm;HotSpot 架构索引见 hotspot。GC 算法细节见 java-gc;JIT 与分层编译见 hotspot-jit。 参数分类 HotSpot 命令行参数分三类: 类型 前缀 说明 标准参数 - 规范要求所有实现支持,如 -version 非标准参数 -X 实现相关,如 -Xms、-Xmx;不保证跨版本兼容 不稳定参数 -XX HotSpot 专有调优项,可能无预警变更或移除 查看当前生效的 HotSpot 参数: java -XX:+PrintCommandLineFlags -version java -XX:+PrintFlagsFinal -version | grep -i gc 堆与元空间 堆大小 参数 别名 说明 -Xms<size> -XX:InitialHeapSize 初始堆大小;常与 -Xmx 设相同,避免运行期扩堆 -Xmx<size> -XX:MaxHeapSize 最大堆大小 -Xmn<size> -XX:NewSize 等 年轻代大小(eden + 2×survivor);显式设置会干扰 G1 等区域自适应,现代应用更常用比例或交给 G1 自动调整 <size> 可用 k/m/g(如 -Xmx2g)。 ...

Created 19196-06-19 · Updated 15156-07-15 · 3 min · 442 words · -

JDK 1.3

JDK 1.3(对外称 Java 2 Platform, Standard Edition, v1.3,代号 Kestrel)于 2000 年 5 月 8 日发布,是 JDK 1.2 之后又一次以运行时为核心的升级——最重要的变化不在语言语法,而在 JVM 本身:HotSpot 从此成为默认 VM。命名与后续演变见 Java 版本历史。 版本号说明 维度 JDK 1.3 对外名称 Java 2 SE 1.3 / JDK 1.3 代号 Kestrel java.version 1.3.x class major version 47 上一版本 JDK 1.2 下一版本 JDK 1.4 概览 JVM:HotSpot 成为默认 VM 这是 1.3 最重要的变化。HotSpot 早在 1999 年 4 月就以独立产品 Java HotSpot Performance Engine 发布,可配合 JDK 1.2 使用,但当时不是默认项;JDK 1.3 起 HotSpot 成为默认 VM,旧的 Classic VM 仍可通过参数选用,直到 JDK 1.4 才被彻底移除。详见 HotSpot。 ...

Created 14146-07-14 · Updated 15156-07-15 · 3 min · 437 words · -

JDK 1.2

JDK 1.2(对外称 Java 2 Platform, Standard Edition, v1.2,代号 Playground)于 1998 年 12 月 8 日发布,是 JDK 1.1 之后的一次「平台级」大版本——类库规模扩大近三倍(约 1520 个类、59 个包),并首次启用 Java 2 品牌。命名与后续演变见 Java 版本历史。 版本号说明 维度 JDK 1.2 对外名称 Java 2 SE 1.2 / JDK 1.2 代号 Playground java.version 1.2.x class major version 46 上一版本 JDK 1.1 下一版本 JDK 1.3 「Java 2」中的 2 指平台代际(1.2 这次大改),并非版本号跳到了 2.0;这一代还拆出了 J2SE / J2EE / J2ME 三个平台方向。完整命名脉络见 Java 版本历史。 概览 语言 strictfp 关键字:约束浮点运算严格遵循 IEEE 754,保证跨平台一致性;这个「严格模式 vs. 默认模式」的区分后来被认为没必要,JDK 17 的 JEP 306 让所有浮点运算恢复为始终严格,strictfp 从此变成没有实际效果的保留字(详见下文「与现代 Java 的关系」) 类库 集合框架(java.util.Collection / List / Set / Map 等):统一的容器体系,ArrayList、HashMap、HashSet 等新增实现;1.0/1.1 的 Vector、Hashtable 被改造为实现 List / Map 接口以便互操作(详见 Collection List Set Map 区别) Swing(javax.swing)并入核心,与 AWT、Java 2D、Accessibility、Drag and Drop 一起构成 JFC(Java Foundation Classes) java.lang.ref:软引用(SoftReference)、弱引用(WeakReference)、虚引用(PhantomReference),配合 ReferenceQueue 提供比 finalize() 更可控的对象回收前/回收后通知机制 Java 2D API(java.awt.geom 等):矢量图形、坐标变换、复杂渲染 拖放 API(java.awt.dnd):跨组件、跨应用的拖放交互 Accessibility API(javax.accessibility):屏幕阅读器等辅助技术支持 Java IDL(org.omg.CORBA):内置 CORBA ORB,是后续 RMI-IIOP(JDK 1.3)的基础 安全模型重写:java.security.Policy / ProtectionDomain 引入细粒度、可配置的权限模型,取代 1.1「Applet 沙箱 vs. 本地代码完全信任」的二元划分 Java Plug-in:让浏览器脱离自带(常常过时)的 JVM,改用独立安装、可控版本的 JRE 运行 Applet JVM 与性能 内置改进版 JIT 编译器——但仍是 Classic VM 自带的实现,不是 HotSpot(HotSpot 此时尚未发布,详见下文「与 HotSpot 的关系」) 默认虚拟机依旧是 Classic VM;HotSpot 要到 JDK 1.3 才成为默认项 1.2 尚未具备(后续版本才加入) 能力 大致引入版本 HotSpot 成为默认 VM 1.3 RMI 可选兼容 CORBA IIOP 1.3 JNDI 并入核心 1.3 assert、NIO、标准正则 1.4 泛型、enum、for-each、JUC 5 集合框架 1.0/1.1 只有 Vector、Hashtable、Stack 等各自为政的容器类,缺少统一抽象。1.2 引入的集合框架用一组接口(Collection、List、Set、Map)加多种实现(ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap)统一了这块: ...

Created 14146-07-14 · Updated 15156-07-15 · 3 min · 536 words · -

开发期热替换(HotSwap、DCEVM、HotSwapAgent)

背景 开发时希望改 Java 代码后 少重启 就能看到效果。这与生产上 BTrace attach 观测 不是同一条路。本文归纳 HotSwap 及相关工具,并说明各自边界。 字节码织入与 redefine 机制见 java-asm;调试协议见 JPDA、JVMTI。 HotSwap 是什么 HotSwap(热替换)泛指:不重启整个 JVM,把 已在内存中的类 换成新字节码。 HotSpot 自带 的热替换能力很窄(通过 调试器 触发,底层 JVMTI / redefine): 常见成功:改 已有方法的方法体 常见失败:新增方法/字段、改签名、改继承、新 import 等 因此 IDE 在 Debug 下保存后提示 “Hot swap” 成功或失败,依赖的是 JPDA → JDWP → JVMTI,不是 Attach API 加载 BTrace agent 那条栈。 开发期 HotSwap(典型) IDE 编译 .class → JDWP 命令 → JVM redefine 已加载类 生产期 BTrace(对比) loadAgent → Instrumentation + ASM retransform → 插探针(观测) 几种开发期方案 方案 怎么做 能力边界 IDE HotSwap Debug + JPDA 方法体为主,标准 HotSpot 最严 JRebel 商业 agent 类加载/字节码策略更激进,需授权 DCEVM 替换/并行使用 修改版 HotSpot(-XXaltjvm=dcevm) 放宽 redefine:可加删方法/字段等 HotSwapAgent -javaagent:hotswapagent.jar + 常配合 DCEVM 用 Javassist 改字节码;插件重载 Spring/Hibernate 等配置 Spring Boot DevTools 双 ClassLoader 快速 Restart 重建 Spring 上下文,不是 JVM 级 HotSwap Spring DevTools 细节见 Spring Boot DevTools。 ...

Created 17176-12-17 · Updated 31316-05-31 · 2 min · 224 words · -

JVMTI(Java 虚拟机工具接口)

背景 调试器断点、IDE 热替换、jcmd 部分能力、Attach API 的 loadAgentLibrary、native agent,底层都依赖 JVM 提供的 native 级 工具接口。在 HotSpot/OpenJDK 上,这一层主要是 JVMTI。 JVMTI 是什么 JVMTI(Java Virtual Machine Tool Interface)是 JVM 实现的 C 语言 native 接口(jvmti.h),用于: 调试:断点、单步、查看栈与局部变量 分析:采样、分配追踪 类与字节码:监听类加载、重定义已加载类(与 IDE HotSwap 相关) Agent:native agent 在 Agent_OnLoad 里通过 JavaVM::GetEnv 拿到 jvmtiEnv 它 不是 Java 应用直接 import 的包;Java 侧看到的是更高层的封装。 前身(已淘汰) 用途 JVMDI 调试 JVMPI 性能分析 JDK 5+ 由 JVMTI 统一替代(见 JPDA 文中的历史说明)。 与 JPDA、Instrumentation 的关系 IDE / jdb(调试器) ↓ JDI(Java API) ↓ JDWP(线协议,如 dt_socket) ↓ JVMTI Agent(如 jdwp.so)→ JVMTI 调用 ↓ HotSpot JVM java.lang.instrument(Java Agent,premain/agentmain) ↓ JVM 内部同样依赖 JVMTI 等 native 能力实现 redefine/retransform 接口 语言 典型用途 JVMTI C / native 调试器后端、profiler、native agent JPDA(JDI + JDWP + JVMTI) 调试体系 Eclipse/IDEA 远程调试、JDB java.lang.instrument Java BTrace、Arthas、-javaagent、部分 APM 三者都落在 同一 JVM 进程 里,但入口不同:写 Java 诊断 agent 用 instrument + Attach;写调试器走 JPDA;写 native 库 agent 用 JVMTI + loadAgentLibrary。 ...

Created 31316-05-31 · Updated 31316-05-31 · 1 min · 195 words · -