Java 的三十年:从 Oak、JVM 到 Kotlin
从嵌入式设备上的 Oak 到企业后端与 Android:梳理 Java 的由来、主要版本语言特性、JVM 执行模型,以及 Kotlin 为什么能在 Java 生态中成长。
Java 已经三十多年了。
它经历过浏览器 Applet 的繁荣与消失,经历过桌面程序、功能手机、企业服务器和 Android,又从“写法古老”的印象里重新长出 Lambda、record、模式匹配与虚拟线程。今天说“Java”,我们可能同时在说三件不同的东西:
- 一门刻意保持克制的编程语言;
- 一套标准库和开发工具组成的平台;
- 一个让 Java、Kotlin、Scala 等语言共同运行的虚拟机生态。
只看语法,很难解释 Java 为什么能活这么久;只谈 JVM,也会错过它近年来明显加快的语言演进。本文试着把这几条线重新接起来。
如果你还想从另一侧比较 JVM 与 .NET 的平台路线,可以接着读 .NET 的平台弯路。
1从 Oak 到 Java:它最早不是为 Web 发明的
Java 的前身叫 Oak。它最初面向嵌入式消费电子设备,由 James Gosling 在 Sun Microsystems 的 Green 项目中设计。后来团队发现早期设备市场没有按预期成熟,才把方向转向互联网,并将语言重新命名、调整为我们后来认识的 Java。早期语言规范对这段转向有明确记载。4
这个出身解释了 Java 最重要的设计目标:
设备和操作系统各不相同
↓
编译到统一的中间格式
↓
每个平台实现自己的虚拟机
↓
同一份程序在不同机器上运行1995 年,Java 随 Web 浪潮公开亮相;1996 年发布的 Java 1.0 把“简单、面向对象、健壮、安全、架构中立、可移植”写进了平台的自我描述。5
当时最吸引眼球的是 Applet:浏览器下载字节码,再在沙箱中执行交互程序。Applet 后来退出历史舞台,但支撑它的核心思想——稳定的二进制格式、运行时验证、跨平台虚拟机——并没有消失。真正活到今天的,不是“网页里的小程序”,而是 Java 平台。
2006 年,Sun 开始把 HotSpot、javac 与 JDK 的主要代码以开源方式发布,OpenJDK 逐渐成为 Java 开发的共同上游。2010 年 Oracle 完成对 Sun 的收购,也成为 Java 的主要维护者之一。67
2先拆开几个经常混用的名字
| 名称 | 它是什么 | 典型内容 |
|---|---|---|
| Java language | 编程语言 | 类、接口、泛型、Lambda、record、模式匹配 |
| JVM | 虚拟机规范及其实现 | 加载、验证和执行 .class 字节码,管理内存与线程 |
| Java SE | 标准平台规范 | 语言、JVM、java.* 标准 API |
| JDK | 开发工具包 | JVM、标准库、javac、java、javadoc、jlink 等 |
| JRE | 传统上的运行环境 | JVM + 运行所需类库;现代 JDK 发行方式中不一定单独提供 |
这里最容易犯的错误,是把 JVM 当成“Java 解释器”。JVM 首先是一份抽象机器规范;HotSpot 才是最常见的具体实现。一个 JVM 可以先解释字节码,也可以把热点代码即时编译为机器码,甚至采用 AOT 等其他实现策略。规范并不要求某一种固定执行方式。8
3主要版本:Java 是怎样一点点变成现代语言的
Java 的版本号经历过一次品牌变化:1.2 到 1.4 常被称为 Java 2,1.5 对外改称 Java 5,此后使用整数版本号。2017 年 Java 9 之后,JDK 进入大约每六个月一个功能版本的节奏;这不意味着每半年都必须迁移生产系统,LTS 仍然承担长期落点。
| 版本 | 时间 | 代表性的语言与平台变化 |
|---|---|---|
| 1.0 | 1996 | 类、接口、异常、线程、GC、字节码与跨平台运行模型 |
| 1.1 | 1997 | 内部类;JDBC、反射、RMI、JavaBeans 等平台能力成熟 |
| 1.2 / Java 2 | 1998 | Collections Framework、Swing;平台开始形成完整桌面与基础类库体系 |
| 1.4 | 2002 | assert;NIO、正则表达式、日志等标准库能力 |
| 5 | 2004 | 泛型、注解、枚举、自动装箱、增强 for、可变参数、静态导入 |
| 6 | 2006 | 语言变化很少,重点转向性能、工具、Web Services 与平台成熟度 |
| 7 | 2011 | try-with-resources、菱形语法、字符串 switch、multi-catch;JVM 加入 invokedynamic |
| 8 | 2014 | Lambda、方法引用、接口默认方法;Stream、Optional、java.time |
| 9 | 2017 | 模块系统 JPMS、JShell、集合工厂方法;版本发布节奏改变 |
| 10 | 2018-03 | 局部变量类型推断 var |
| 11 LTS | 2018-09 | Lambda 参数可用 var;标准 HTTP Client,长期维护的新基线 |
| 14–17 | 2020–2021 | switch 表达式、文本块、record、instanceof 模式匹配、sealed class 先后稳定;17 为 LTS |
| 18–21 | 2022–2023 | UTF-8 成为默认字符集;record pattern、模式匹配 switch;Java 21 LTS 正式加入虚拟线程 |
| 22 | 2024-03 | 未命名变量与模式 _ 稳定;FFM API 稳定,连接原生函数与堆外内存 |
| 23–24 | 2024–2025 | 语言侧以预览迭代为主;24 加入正式 Class-File API,继续推进启动与运行时能力 |
| 25 LTS | 2025-09 | 模块导入声明、紧凑源文件与实例 main、灵活构造函数体稳定 |
| 26–27 | 2026 | 无新的永久语言特性;primitive pattern matching 继续预览,运行时、库与安全能力仍持续演进 |
版本日期与 Java 9 之后的正式/预览语言特性,可在 Oracle 的语言变更总表与 Java SE 规格页交叉核对。910
这张表很长,但 Java 的语言演进其实可以压缩成四次明显转向。
4Java 5:让类型系统和框架真正长大
Java 5 是第一轮大改造。此前集合通常存放 Object,取出时再强制转换:
List names = new ArrayList();
names.add("Duke");
String name = (String) names.get(0);有了泛型:
List<String> names = new ArrayList<>();
names.add("Duke");
String name = names.get(0);泛型把很多错误提前到编译期,也成为集合、依赖注入、ORM 与现代框架 API 的基础。但 Java 为了兼容既有字节码,采用了 类型擦除:大多数泛型实参不会作为对象的运行时类型保存,编译器会擦除类型参数、插入必要的转换,并生成 bridge method。11
这带来几个延续至今的限制:
new T(); // 不允许
value instanceof List<String>; // 不允许检查具体泛型实参
List<int> values; // primitive 不能直接作为类型实参同一版本的注解也极为重要。今天常见的 Spring、JUnit、Jackson、Android 与编译期代码生成,都大量依赖注解和反射/处理器建立声明式模型。Java 5 看起来只是加了几组语法,实际上为后来的框架文化搭好了骨架。
5Java 8:从“只有类”走向函数式组合
Java 8 是另一座分水岭。它没有放弃面向对象,而是把函数式表达能力接进了已有的接口系统。
Java 7 时代:
Collections.sort(users, new Comparator<User>() {
@Override
public int compare(User a, User b) {
return a.name().compareTo(b.name());
}
});Java 8:
users.sort(Comparator.comparing(User::name));
List<String> activeNames = users.stream()
.filter(User::active)
.map(User::name)
.sorted()
.toList();这里不是简单把匿名类缩短成箭头:
- 函数式接口让 Lambda 可以适配既有的单一抽象方法接口;
- 接口默认方法允许给已有接口增加能力,同时尽量保持二进制兼容;
- Stream API提供内部迭代、惰性流水线与并行处理模型;
- 方法引用让已有对象模型与函数式组合自然连接。
Java 8 也解释了 Java 的典型演进方式:不另起一套互不兼容的语言,而是在旧抽象上寻找一条能让历史代码继续工作的扩展路径。
Stream 不等于集合,也不保证更快
Stream 是一次性消费的计算流水线,不是存储数据的容器。它擅长表达筛选、映射、聚合;parallelStream() 也不会自动让业务更快。数据规模、拆分成本、共享状态与所用线程池,都会影响结果。
6Java 9 之后:模块、半年发布与 Preview
Java 9 的 JPMS 模块系统试图解决 JDK 和大型应用长期存在的几个问题:依赖边界模糊、内部 API 被随意访问、运行镜像过大。module-info.java 可以显式声明需要什么、导出什么:
module com.example.order {
requires java.sql;
exports com.example.order.api;
}模块化让 JDK 能用 jlink 组合出更小的运行镜像,也加强了内部包封装;代价是从 Java 8 迁移时,反射框架、深度依赖 JDK 内部 API 的库经常需要调整。
更深远的变化是发布方式。过去一个大版本可能等待多年;Java 9 之后,功能可以在较短周期内交付,并通过 Preview Feature 反复获取反馈。
Preview 不是“文档写得还不完整”,而是有意暂未永久承诺的语言或 VM 特性。它需要显式启用,也可能修改甚至撤回。String Templates 在 Java 21、22 预览后于 23 撤回,就是很好的例子。9
快发布,不等于激进定型
Java 现在的节奏更快,但语言设计仍然保守:一个特性可以连续多个版本预览,直到语义和迁移成本足够清楚。半年发布解决的是“等待交付太久”,Preview 解决的是“不要太早把设计永久写进语言”。
7Java 14–21:数据建模、模式匹配与虚拟线程
现代 Java 最明显的变化,是过去冗长的“数据类 + 类型判断”开始被语言直接表达。
7.1record:数据载体不再手写样板代码
record User(long id, String name, String email) {}编译器会生成组件访问器、构造器、equals、hashCode 和 toString。record 不是“字段可以随便改的 Lombok 类”,而是明确表达:这个类型的主要语义来自声明中的数据状态。Record 在 Java 16 正式交付。12
7.2sealed class + pattern matching:封闭领域模型
sealed interface Result permits Success, Failure {}
record Success(String value) implements Result {}
record Failure(int code, String message) implements Result {}
String describe(Result result) {
return switch (result) {
case Success(var value) -> value;
case Failure(var code, var message) -> code + ": " + message;
};
}sealed hierarchy 告诉编译器子类型集合是受控的,record pattern 把数据解构出来,模式匹配 switch 则检查分支是否穷尽。这让 Java 能更自然地表达编译器 AST、协议消息、状态机和业务结果。
7.3虚拟线程:保留阻塞式写法,改变线程成本
Java 21 正式加入 Virtual Threads。它们仍然是 java.lang.Thread,但不再要求每个 Java 线程在整个生命周期中独占一个操作系统线程。JVM 把大量虚拟线程调度到较少的平台线程上,适合存在大量等待的 I/O 服务。13
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 10_000; i++) {
executor.submit(() -> fetchRemoteData());
}
}它的价值不是让 CPU 密集算法凭空加速,而是让“一个请求一个线程”的直线式代码,在高并发 I/O 场景中不再需要同样数量的昂贵 OS 线程。
8Java 25:一边降低入门门槛,一边修补老限制
Java 25 LTS 的三个正式语言特性很能说明今天的方向。
紧凑源文件与实例 main 让初学者不必先理解 public static void main(String[] args) 的全部仪式:
void main() {
IO.println("Hello, Java");
}模块导入声明可以一次导入某个模块导出的包:
import module java.base;灵活构造函数体允许在 super(...) 或 this(...) 之前进行不访问当前实例的参数验证与准备工作:
final class PositiveBigInteger extends BigInteger {
PositiveBigInteger(long value) {
if (value <= 0) throw new IllegalArgumentException("value <= 0");
super(Long.toString(value));
}
}这些变化没有 Java 8 Lambda 那样轰动,却在处理真实摩擦:让第一段 Java 更短,让模块 API 更容易使用,让构造器能在父类构造前可靠验证输入。它们在此前多个版本预览,直到 Java 25 才稳定。14
9JVM 到底做了什么
一段 Java 或 Kotlin 程序在 HotSpot 上运行,可以先画成这条简化路径:
9.1.class 才是 JVM 真正认识的语言
JVM 规范写得很直接:虚拟机并不了解 Java 语言本身,它只了解 class 文件格式。只要一门语言能生成合法字节码,就可以把 JVM 当成发布平台。8
这就是 Kotlin、Scala、Clojure、Groovy 能和 Java 共处的根本原因,也是 Java 生态真正的护城河:
不同源语言
→ 相同 class / JAR / 模块边界
→ 相同 GC、JIT、调试器、Profiler
→ 可以调用同一批 Java 类库9.2类加载不只是“把文件读进来”
JVM 会经历加载、链接与初始化。链接又包含验证、准备、解析等阶段。字节码验证会检查结构和类型约束,避免把任意字节误当成可执行 JVM 指令;类加载器则让应用服务器、插件系统和框架能够建立相互隔离或动态扩展的类型空间。
同名类由不同类加载器加载时,可以被 JVM 视为不同类型。这是 Java 插件机制强大的来源,也是 ClassCastException、依赖冲突和容器泄漏中最让人头疼的一类问题。
9.3JIT:Java 为什么会“先热身,再变快”
HotSpot 通常不会在程序启动时把所有代码一次性编译到最高优化级别。它先解释或快速编译代码,并收集真实运行画像:哪些方法最热、分支通常走哪边、调用点实际上出现了哪些类型。随后 C1/C2 分层编译器可以做内联、逃逸分析、去虚拟化等优化。HotSpot 的分层编译默认使用 C1 与 C2。15
这解释了两个常见现象:
- 微基准如果没有正确预热,很容易测到编译过程而非稳定吞吐;
- 长期运行的服务可能获得很高的峰值性能,但传统 JVM 的启动时间和内存占用也会成为命令行工具、Serverless 与小容器的痛点。
OpenJDK 的 Project Leyden 正在把更多类加载、链接、画像乃至部分编译工作前移,目标就是改善启动时间、达到峰值性能的时间和内存占用。16
9.4GC:自动管理内存,不等于没有内存问题
JVM 的堆由垃圾收集器回收不再可达的对象。具体算法不是 JVM 规范固定的一部分;HotSpot 可以提供面向吞吐、低停顿或超大堆的不同收集器。
自动回收解决的是“何时释放不可达对象”,不是“对象一定不会占太多内存”。缓存无上限、监听器不注销、ThreadLocal 生命周期过长、类加载器仍被引用,都可以造成逻辑上的内存泄漏。理解可达性、分配速率和 GC 日志,仍然是大型 Java 服务的基本功。
10Kotlin 为什么会出现
Kotlin 由 JetBrains 在 2010 年启动,2016 年发布 1.0。它不是因为 JVM 失败才出现,恰恰相反:JVM、Java 类库和构建生态已经很成功,但 Java 语言在很多日常表达上显得冗长。 Kotlin 选择保留平台,替换上层语言体验。2
一个典型 Java 数据类型:
record User(String name, String email) {
String displayName() {
return email == null ? name : name + " <" + email + ">";
}
}对应 Kotlin:
data class User(
val name: String,
val email: String?,
) {
fun displayName(): String =
email?.let { "$name <$it>" } ?: name
}现代 Java 的 record 已经缩小了样板代码差距,但 Kotlin 的重点仍然很明确:
String与String?在类型系统中区分非空与可空;data class自动提供值语义常用成员和copy;- 属性、默认参数、命名参数减少 getter/setter 和重载;
- extension function 在不修改原类的情况下增加调用形式;
- smart cast 根据控制流自动收窄类型;
- sealed class/interface 与
when适合封闭状态建模; suspend与kotlinx.coroutines提供结构化的异步编程模型。
Kotlin 后来也发展到 JavaScript、Native、Wasm 与 Multiplatform,但 Kotlin/JVM 仍然是它最成熟、最容易理解的落点:编译器生成 Java 兼容的 class 文件,运行在同一个 JVM 上。
11Kotlin 与 Java 怎样互操作
Kotlin 从设计之初就重视 Java 互操作。大多数 Java 类可以直接在 Kotlin 中调用,Java 也能创建和调用 Kotlin 编译出的类。JavaBean getter/setter 在 Kotlin 中通常表现为属性,Java SAM interface 可以直接接收 Kotlin Lambda。17
val executor = Executors.newSingleThreadExecutor()
executor.execute { println("running") } // Runnable SAM conversion这种兼容性让团队不必重写整个项目:同一个 Gradle/Maven 工程里可以逐个文件、逐个模块迁移。Android 的 Kotlin-first 路线也建立在这一点上——Google 优先为 Kotlin 提供新的示例与扩展,同时继续支持 Java API。18
但“可互调”不等于“语义完全相同”。
11.1Platform type:空安全边界上的妥协
普通 Java 签名未必说明一个引用能否为 null。Kotlin 导入时会形成 platform type;调用者可以把它当可空或非空使用,编译器无法提供纯 Kotlin 代码里同样强的保证。
// Java:没有 nullability annotation
String findName();val name = legacy.findName() // 可能被推断为平台类型 String!
println(name.length) // 若 Java 实际返回 null,仍可能在运行时失败因此混合项目里的 nullability annotation、清晰 API 边界和渐进迁移,比“把文件扩展名全改成 .kt”更重要。
11.2默认参数、属性与伴生对象会映射成 JVM 结构
Kotlin 的属性通常编译成字段加 getter/setter;默认参数依赖编译器生成的调用约定,Java 调用者若需要传统重载,常用 @JvmOverloads;伴生对象、顶层函数、值类等也各有自己的字节码映射与 @JvmStatic、@JvmName 等互操作工具。
如果一个库主要给 Java 用户使用,API 设计者最好从 Java 侧实际调用一次,而不是只看 Kotlin 源码是否优雅。
11.3泛型并没有因为换成 Kotlin 就获得完整运行时实化
Kotlin/JVM 同样运行在现有 JVM 泛型模型上,普通泛型仍然擦除。Kotlin 的 inline + reified 能让特定内联函数在调用点保留类型实参操作,但它不是把所有 JVM 泛型都变成了具化泛型。17
12Kotlin 协程与 Java 虚拟线程,不是同一个东西
这两者都能让高并发代码更易读,因此经常被放在一起比较,但抽象层级不同。
| Kotlin coroutine | Java virtual thread | |
|---|---|---|
| 核心抽象 | 可挂起、恢复的计算 | java.lang.Thread 的轻量实现 |
| 调度 | 由 coroutine dispatcher / library 控制 | 由 JVM 虚拟线程调度器映射到平台线程 |
| API 风格 | suspend、scope、launch、async | 阻塞式 Thread / Executor API |
| 生态接入 | 调用链需要理解 suspending API | 大量既有阻塞 API 可直接使用 |
| 取消与结构化并发 | kotlinx.coroutines 已有成熟模型 | Structured Concurrency 仍在 Java 平台持续预览 |
Kotlin 的 suspend 是语言能力,但 launch、async、dispatcher 等主要来自 kotlinx.coroutines 库;协程最终仍在线程上运行,挂起时可以释放线程去做别的工作。19
虚拟线程则让传统阻塞式代码获得更低的线程成本。它不自动提供 Kotlin coroutine scope 的全部生命周期语义,也不会让 CPU 密集任务突破核心数限制。
怎么选
- 已有 Java/Spring 同步代码,希望少改动获得高 I/O 并发:先评估虚拟线程。
- Android、Compose 或已经围绕 suspending API 设计的 Kotlin 项目:协程通常更自然。
- 新系统不要只看“能开多少任务”;取消传播、超时、监控、ThreadLocal/上下文传递和第三方库行为同样重要。
13今天该选 Java,还是 Kotlin
这不是“旧语言与新语言”之间的单选题,因为二者大量共享同一个运行时和生态。
13.1更适合优先考虑 Java 的情况
- 团队、框架和运维体系已经以 Java 为共同语言;
- 公共库需要面对最广泛的 JVM 使用者;
- 希望减少编译器插件、额外运行库和跨语言调试复杂度;
- 项目更看重长期兼容、人员供给与升级可预测性;
- Java 17/21/25 的 record、pattern matching、virtual threads 已经满足主要需求。
13.2更适合优先考虑 Kotlin 的情况
- Android 与 Jetpack Compose 开发;
- 业务模型大量受益于空安全、sealed hierarchy、extension 与 DSL;
- 团队愿意统一 Kotlin 风格、构建设置和 Java 互操作规范;
- 已经使用协程生态,且能让异步边界从 UI/API 一直贯穿到数据层;
- 需要在 JVM 之外探索 Kotlin Multiplatform,同时接受各目标平台成熟度不同。
真正需要避免的,是在没有边界规则时随意混写:Java API 暴露模糊的 nullability,Kotlin API 生成难用的 Java 签名,两个异步模型再互相套娃。混合语言本身不是问题,没有明确的模块边界与互操作设计才是问题。
14Java 为什么能活到今天
Java 的优势从来不只是某一个语法特性。它真正长期有效的组合是:
相对克制的语言演进
+ 稳定、版本化的 class 文件
+ 成熟的 JIT / GC / 诊断工具
+ 庞大的库、框架与工程人才
+ 很强的二进制兼容意识这种克制也有代价。类型擦除、primitive 与 object 的分裂、启动和预热成本,都不是靠几行语法糖能消失的问题。OpenJDK 仍在通过 Valhalla 探索更紧凑的值/原始类型与泛型,通过 Leyden 改善启动、预热和占用;这些工程之所以漫长,正是因为 Java 不愿轻易牺牲已经运行几十年的代码。2016
Kotlin 的出现并没有推翻这套平台,反而证明了它的价值:当上层语言不够顺手时,团队可以换一种语言,继续使用 JVM、Java 类库、构建工具和部署体系。
收束
Java 的故事不是“一门 1990 年代语言勉强活到现在”,而是三层系统彼此托举:
- Java language 用克制的方式持续吸收泛型、Lambda、record、模式匹配与更轻量的并发;
- JVM 把源码语言与机器、操作系统隔开,并用 JIT、GC 与稳定字节码承担平台价值;
- Kotlin 等 JVM 语言 在不丢掉生态的前提下,继续试探更现代的表达方式。
Java 最成功的发明,也许不是某个关键字,而是把“语言”和“运行平台”分开。Oak 消失了,Applet 消失了,很多框架也会消失;只要 .class、JVM 与兼容性承诺仍然成立,这个生态就还能继续演化。
注释
-
Oracle,Java SE Support Roadmap,更新于 2026-09-15。列出 Java 25 为 LTS、Java 27 为 2026 年 9 月非 LTS 功能版,以及后续支持计划;具体免费使用与商业支持期限取决于发行版和许可。 ↩
-
Kotlin Documentation,FAQ。说明 Kotlin 项目始于 2010 年、1.0 发布于 2016 年,以及截至本文日期的稳定版 2.4.20。 ↩ ↩2
-
Kotlin Documentation,FAQ: Which versions of JVM does Kotlin target?。说明 Kotlin/JVM 默认生成 Java 8 兼容字节码,并列出当前可选 JVM target 范围。 ↩
-
Oracle,《Java Language Specification》第一版前言,Preface to the First Edition。说明 Java 原名 Oak、最初面向嵌入式消费电子,并在后来转向互联网。 ↩
-
James Gosling、Henry McGilton,1996,The Java Language Environment。早期官方白皮书列出简单、健壮、安全、架构中立、可移植等设计目标。 ↩
-
OpenJDK Wiki,JBS Overview。记录 2006 年 HotSpot 与
javac开源、2007 年 JDK 7 大部分源码发布的时间线。 ↩ -
Oracle,2010,Oracle and Sun Overview。记录 Oracle 于 2010 年 1 月完成对 Sun Microsystems 的收购。 ↩
-
Oracle,《Java Virtual Machine Specification 25》,Introduction。说明 JVM 是抽象机器、只认识
class格式而不认识 Java 源语言,并允许其他语言以 JVM 为目标平台。 ↩ ↩2 -
Oracle,Java Language Changes Summary。汇总 Java 9–27 的正式、预览及撤回语言特性。 ↩ ↩2
-
Oracle,Java SE Specifications。列出 Java SE 25、26、27 的正式规格与发布日期,支撑本文“最新正式版 Java 27”的判断。 ↩
-
Oracle Java Tutorials,Type Erasure。说明 Java 编译器如何擦除泛型参数、插入转换并生成 bridge method。 ↩
-
OpenJDK,JEP 395: Records。记录 record 在 JDK 16 正式交付的设计目标与语义。 ↩
-
OpenJDK,JEP 444: Virtual Threads。说明虚拟线程在 Java 21 正式交付、M:N 调度目标,以及其适合高吞吐 I/O 而非提升 CPU 密集计算速度。 ↩
-
Oracle,Significant Changes in JDK 25。说明模块导入、紧凑源文件与实例
main、灵活构造函数体在 Java 25 稳定。 ↩ -
Oracle,Java HotSpot Virtual Machine Performance Enhancements。说明 HotSpot 默认的 C1/C2 分层编译及运行时画像优化。 ↩
-
OpenJDK,Project Leyden。项目目标是改善 Java 程序的启动时间、达到峰值性能的时间和占用,并列出已交付与进行中的 AOT 工作。 ↩ ↩2
-
Kotlin Documentation,Calling Java from Kotlin 与 Calling Kotlin from Java。说明属性映射、SAM 转换、platform type 与泛型擦除等互操作规则。 ↩ ↩2
-
Android Developers,Android's Kotlin-first approach。说明 Android 自 2019 年采用 Kotlin-first 的工具、文档与 API 方向,同时继续支持 Java。 ↩
-
Kotlin Documentation,Coroutines basics。说明
suspend属于语言,而大多数协程能力来自kotlinx.coroutines;协程在 JVM 上仍运行于线程并可在挂起时释放线程。 ↩ -
OpenJDK,State of Valhalla: Background。设计说明介绍扁平化值类型与 specialized generics 的目标;属于进行中的 OpenJDK 项目,不代表已经进入正式 Java 语言。 ↩
CONTINUE EXPLORING