引言

Java 8到Java 17的升级是企业级应用现代化的重要步骤。本文全面介绍升级过程中的关键变化,特别关注JVM和GC的优化。

语言特性变化

Java 8到Java 17各版本关键特性

Java 9 (2017年9月)

  • **模块化系统 (JPMS)**:引入模块化概念,提高安全性和可维护性
  • JShell:交互式Java REPL工具
  • 集合工厂方法List.of(), Set.of(), Map.of()
  • 接口私有方法:接口中可以定义私有方法
  • HTTP/2客户端:新的HTTP客户端API

Java 10 (2018年3月)

  • **局部变量类型推断 (var)**:简化局部变量声明
  • 应用类数据共享:提升启动性能
  • 并行全GC:改进G1 GC的并行处理能力

Java 11 (2018年9月) - LTS

  • HTTP客户端标准化java.net.http
  • 启动单文件源代码:直接运行.java文件
  • String增强方法isBlank(), lines(), repeat(), strip()
  • Lambda参数类型推断var可用于lambda参数

Java 12 (2019年3月)

  • Switch表达式预览:更简洁的switch语法
  • 字符串缩进方法indent()transform()
  • Shenandoah GC:低暂停GC算法

Java 13 (2019年9月)

  • 文本块预览:多行字符串处理
  • Switch表达式增强yield关键字
  • ZGC改进:支持返回未使用的堆内存

Java 14 (2020年3月)

  • Record类预览:简化数据类定义
  • Switch表达式正式版:标准化的switch表达式
  • instanceof模式匹配预览:简化类型检查和转换
  • NullPointerException增强:更详细的错误信息

Java 15 (2020年9月)

  • 文本块正式版:标准化的多行字符串
  • Sealed类预览:限制类的继承
  • 隐藏类:框架内部使用的类
  • ZGC和Shenandoah GC:生产就绪

Java 16 (2021年3月)

  • Record类正式版:标准化的数据类
  • instanceof模式匹配正式版:标准化的类型检查
  • Stream API增强toList(), mapMulti()
  • Vector API孵化:SIMD向量计算

Java 17 (2021年9月) - LTS

  • Sealed类正式版:标准化的继承控制
  • 模式匹配switch预览:更强大的switch语句
  • 伪随机数生成器:新的随机数API
  • 移除Applet API:完全移除过时的Applet支持

详细代码示例对比

1. 集合工厂方法 (Java 9+)

1
2
3
4
5
6
7
8
9
10
// Java 8 - 传统方式
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");

// Java 9+ - 工厂方法
List<String> list = List.of("a", "b", "c");
Set<String> set = Set.of("a", "b", "c");
Map<String, Integer> map = Map.of("a", 1, "b", 2);

2. 字符串增强方法 (Java 11+)

1
2
3
4
5
6
7
8
9
// Java 8
String str = " hello ";
if (str.trim().isEmpty()) { /* 处理 */ }

// Java 11+
String str = " hello ";
if (str.isBlank()) { /* 处理 */ }
String stripped = str.strip(); // 去除前后空白
String repeated = "-".repeat(10); // 重复字符串

3. Stream API增强 (Java 16+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Java 8
List<String> result = stream.collect(Collectors.toList());

// Java 16+
List<String> result = stream.toList(); // 更简洁

// Java 16 mapMulti示例
List<String> result = list.stream()
.mapMulti((s, consumer) -> {
if (s.length() > 3) {
consumer.accept(s.toUpperCase());
}
})
.toList();

4. 模式匹配instanceof (Java 16+)

1
2
3
4
5
6
7
8
9
10
// Java 8
if (obj instanceof String) {
String str = (String) obj;
System.out.println(str.length());
}

// Java 16+
if (obj instanceof String str) {
System.out.println(str.length()); // 自动类型转换
}

5. Sealed类继承控制 (Java 17+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Java 17 Sealed类定义
public sealed class Shape
permits Circle, Rectangle, Triangle {
// 基础类定义
}

// 允许的子类
public final class Circle extends Shape {
private double radius;
}

public final class Rectangle extends Shape {
private double width, height;
}

// 编译错误:Triangle不在permits列表中
// public class Triangle extends Shape { } // 错误!

6. 模式匹配switch预览 (Java 17)

1
2
3
4
5
6
7
8
// Java 17 模式匹配switch(预览特性)
String result = switch (obj) {
case Integer i -> "整数: " + i;
case String s && s.length() > 5 -> "长字符串: " + s;
case String s -> "字符串: " + s;
case null -> "空值";
default -> "其他类型";
};

函数式编程增强

Optional增强 (Java 9+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Java 8
Optional<String> opt = Optional.ofNullable(getValue());
if (opt.isPresent()) {
String value = opt.get();
// 处理value
}

// Java 9+
Optional<String> opt = Optional.ofNullable(getValue());
opt.ifPresentOrElse(
value -> System.out.println(value), // 值存在时
() -> System.out.println("值不存在") // 值不存在时
);

// Java 11+
String result = opt.orElseThrow(); // 无参版本

CompletableFuture增强 (Java 9+)

1
2
3
4
5
// Java 9+ 超时支持
CompletableFuture<String> future = CompletableFuture
.supplyAsync(() -> longRunningTask())
.orTimeout(5, TimeUnit.SECONDS) // 5秒超时
.exceptionally(ex -> "超时或错误");

性能优化特性

字符串性能优化 (Java 9+)

  • 紧凑字符串:Latin-1字符使用单字节存储
  • Indify字符串连接:编译时优化字符串拼接

JVM编译器优化 (Java 9+)

  • 分层编译改进:更智能的JIT编译策略
  • AOT编译:提前编译为本地代码(Java 9引入,Java 17移除)

向后兼容性考虑

废弃API迁移指南

  • Java 8 Date APIJava 8+ java.time API
  • Vector/HashtableArrayList/HashMap
  • Thread.stop/suspendinterrupt()机制
  • FinalizerCleaner API (Java 9+)

JVM和GC的重大变化

默认GC的变化

1
2
3
4
5
# Java 8: 默认Parallel GC
-XX:+UseParallelGC

# Java 9-17: 默认G1 GC
-XX:+UseG1GC

新的GC选项

  • ZGC(Java 11引入,Java 15生产就绪):低延迟GC
  • Shenandoah(Java 12引入):低暂停GC
  • Epsilon(Java 11引入):无操作GC,用于性能测试

GC调优参数对比

Java 8 Parallel GC调优:

1
2
3
4
-XX:+UseParallelGC
-XX:ParallelGCThreads=4
-XX:MaxGCPauseMillis=200
-XX:GCTimeRatio=99

Java 17 G1 GC调优:

1
2
3
4
5
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=60
-XX:G1HeapRegionSize=16m

Java 17 ZGC调优(低延迟场景):

1
2
3
4
-XX:+UseZGC
-XX:ConcGCThreads=2
-XX:ParallelGCThreads=4
-Xmx8g -Xms8g # ZGC需要较大堆内存

JVM性能监控增强

Java 8监控工具:

1
2
jstat -gc <pid>
jmap -heap <pid>

Java 17增强监控:

1
2
3
4
5
6
7
# JFR(Java Flight Recorder)免费使用
-XX:StartFlightRecording=filename=recording.jfr

# 新诊断命令
jcmd <pid> GC.heap_info
jcmd <pid> VM.info
jcmd <pid> JFR.start

模块化系统(JPMS)

Java 9引入的模块化系统在Java 17中成熟。关键变化:

  • 自动模块检测
  • 模块路径配置
  • 反射访问限制

反射访问解决方案

1
2
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.util=ALL-UNNAMED

移除的API和功能

  • Java EE和CORBA模块:Java 11移除,需手动添加依赖
  • Nashorn JavaScript引擎:Java 15废弃,Java 17移除
  • Applet API:完全移除
  • 安全管理器:Java 17标记为废弃

升级步骤

1. 依赖兼容性检查

1
2
3
4
5
# Maven
mvn versions:display-dependency-updates

# Gradle
gradle dependencyUpdates

2. 编译参数更新

1
2
3
4
5
# Java 8
javac -source 1.8 -target 1.8

# Java 17
javac --release 17

3. 代码迁移要点

  • 使用新集合工厂方法:List.of(), Set.of(), Map.of()
  • 替换废弃日期API为新的时间API
  • 使用流API增强功能(takeWhile, dropWhile, toList()
  • 应用Optional增强方法

容器环境优化

Java 17容器支持

1
2
3
4
# 自动容器感知(Java 10+)
-XX:+UseContainerSupport
-XX:MaxRAMPercentage=75.0
-XX:InitialRAMPercentage=50.0

Kubernetes部署示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: java-app
resources:
limits:
memory: "2Gi"
requests:
memory: "1Gi"
env:
- name: JAVA_OPTS
value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"

性能优化建议

内存优化

  • 使用G1 GC的字符串去重:-XX:+UseStringDeduplication
  • 合理设置堆大小和年轻代比例
  • 监控内存泄漏:使用jmapjcmd生成堆转储

GC调优策略

Web应用(中等负载):

1
2
3
4
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=60

大数据处理(高吞吐量):

1
2
3
4
-XX:+UseG1GC  
-XX:MaxGCPauseMillis=500
-XX:G1HeapRegionSize=32m
-XX:InitiatingHeapOccupancyPercent=45

低延迟要求应用:

1
2
3
4
-XX:+UseZGC
-XX:ConcGCThreads=4
-Xmx16g -Xms16g
-XX:SoftMaxHeapSize=14g

常见问题解决

问题1:反射访问异常

症状InaccessibleObjectException
解决方案:添加--add-opens参数

问题2:第三方库不兼容

症状NoClassDefFoundError
解决方案:升级库版本或寻找替代方案

问题3:GC性能问题

症状:暂停时间变长
解决方案:调整GC参数,考虑使用ZGC

完整迁移示例

Java 8版本

1
2
3
4
5
6
7
8
9
10
11
12
13
public class UserService {
private List<User> users = new ArrayList<>();

public List<User> findUsersOlderThan(int age) {
List<User> result = new ArrayList<>();
for (User user : users) {
if (user.getAge() > age) {
result.add(user);
}
}
return result;
}
}

Java 17现代化版本

1
2
3
4
5
6
7
8
9
10
11
12
13
public class UserService {
private final List<User> users = List.of(
new User("张三", 25), new User("李四", 30)
);

public List<User> findUsersOlderThan(int age) {
return users.stream()
.filter(user -> user.age() > age)
.toList(); // Java 16+简化语法
}

public record User(String name, int age) { }
}

总结

升级收益

  • 性能提升:新的JVM优化和GC算法
  • 开发效率:现代语言特性简化代码
  • 安全性:更强的安全特性和漏洞修复
  • 长期支持:LTS版本保障

升级建议

  1. 渐进式升级:先在测试环境验证
  2. 性能监控:升级前后对比性能指标
  3. GC调优:根据应用场景选择合适的GC策略
  4. 容器优化:充分利用Java 17的容器感知特性

Java 8到Java 17的升级是技术现代化的关键步骤,合理规划可以显著提升应用性能和开发效率。