
Java 作为企业级应用开发的中流砥柱,其每一次版本更新都备受瞩目。2024 年 9 月,Oracle 正式发布了 Java Development Kit(JDK)25,带来了一系列令人振奋的新特性和改进。从性能飞跃到语法简化,从安全增强到工具链优化,JDK 25 为开发者提供了更强大、更高效的编程工具。
本文将深入剖析 JDK 25 中最值得关注的十大特性,通过通俗易懂的讲解和可直接运行的实例,帮助你全面掌握这个版本的精髓。无论你是 Java 新手还是资深开发者,都能从本文中找到提升开发效率和代码质量的实用技巧。
JDK 25 是 Java SE 平台的第 25 个主要版本,遵循 Java 的 6 个月发布周期,于 2024 年 9 月正式发布,非长期支持(LTS)版本。尽管不是 LTS 版本,JDK 25 依然包含了多项重要更新,为后续 LTS 版本(预计为 JDK 26)奠定了基础。
Java 的版本发布节奏自 2018 年以来一直保持稳定的 6 个月周期,这种模式让开发者能够更快地获取新特性,同时也让 Oracle 能够更灵活地响应社区需求。JDK 25 正是这一策略的延续,汇集了社区反馈和前沿技术探索的成果。

JDK 25 的开发过程中,共有 15 个 JEP(JDK Enhancement Proposal,JDK 增强提案)被正式采纳,涵盖了语言特性、JVM 改进、库增强和工具更新等多个方面。这些提案经过了社区的广泛讨论和严格评审,确保了新特性的实用性和稳定性。
模式匹配自 JDK 16 引入以来,一直在不断演进。JDK 25 通过 JEP 465 进一步增强了模式匹配的能力,主要体现在以下几个方面:
下面通过一个实例来展示这些增强:
package com.example.jdk25.feature;
import lombok.extern.slf4j.Slf4j;
import java.util.Objects;
/**
* 模式匹配增强演示
*
* @author ken
*/
@Slf4j
public class PatternMatchingDemo {
/**
* 员工记录类
*/
public record Employee(String name, int age, Department department) {}
/**
* 部门记录类
*/
public record Department(String name, Location location) {}
/**
* 地点记录类
*/
public record Location(String city, String country) {}
/**
* 演示嵌套记录模式匹配
*
* @param obj 待匹配的对象
*/
public static void demoNestedRecordPattern(Object obj) {
// 嵌套记录模式匹配
if (obj instanceof Employee e
&& e.age() > 30
&& e instanceof Employee(_, _, Department d
&& d instanceof Department("Engineering", Location l
&& l.country().equals("China")))) {
log.info("匹配到中国工程部30岁以上员工: {}", e.name());
}
}
/**
* 演示数组模式匹配
*
* @param obj 待匹配的对象
*/
public static void demoArrayPattern(Object obj) {
// 数组模式匹配
if (obj instanceof int[] {1, 2, var x}) {
log.info("匹配到前两个元素为1,2的整数数组,第三个元素是: {}", x);
} else if (obj instanceof String[] {var first, _, "Java"}) {
log.info("匹配到第三个元素为'Java'的字符串数组,第一个元素是: {}", first);
}
}
public static void main(String[] args) {
// 测试嵌套记录模式
Location beijing = new Location("Beijing", "China");
Department engineering = new Department("Engineering", beijing);
Employee emp = new Employee("Zhang San", 35, engineering);
demoNestedRecordPattern(emp);
// 测试数组模式
demoArrayPattern(new int[] {1, 2, 3});
demoArrayPattern(new String[] {"Hello", "World", "Java"});
}
}上述代码展示了 JDK 25 中模式匹配的主要增强点:
这些增强使得 Java 代码能够更清晰地表达数据结构的解构和验证逻辑,减少了模板代码,提高了可读性。
字符串模板是 JDK 25 中最受期待的特性之一,经过多个预览版本的迭代,终于在 JDK 25 中正式转正。字符串模板提供了一种安全、简洁的方式来拼接字符串和表达式,解决了传统字符串拼接的可读性差和安全隐患问题。
字符串模板使用STR."..."语法,其中可以包含表达式\{...}:
package com.example.jdk25.feature;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
/**
* 字符串模板演示
*
* @author ken
*/
@Slf4j
public class StringTemplatesDemo {
/**
* 演示基本字符串模板功能
*/
public static void basicStringTemplate() {
String name = "Alice";
int age = 30;
// 基本字符串模板
String info = STR."Name: \{name}, Age: \{age}";
log.info(info);
// 多行字符串模板
String multiLine = STR."""
User Information:
Name: \{name}
Age: \{age}
Status: Active
""";
log.info("Multi-line template:\n{}", multiLine);
}
/**
* 演示字符串模板在SQL中的应用
*/
public static void sqlTemplateDemo() {
String tableName = "users";
String column = "name";
String value = "Bob";
// SQL查询模板
String query = SQL."SELECT * FROM \{tableName} WHERE \{column} = \{value}";
log.info("Generated SQL: {}", query);
}
/**
* 演示自定义字符串处理器
*/
public static void customProcessorDemo() {
List<String> fruits = List.of("apple", "banana", "cherry");
// 使用自定义处理器将列表格式化
String formatted = LIST."Fruits: \{fruits}";
log.info(formatted);
}
/**
* 自定义列表格式化处理器
*/
public static final StringTemplate.Processor<String> LIST =
(StringTemplate st) -> {
StringBuilder sb = new StringBuilder();
sb.append(st.fragments().get(0));
// 处理表达式结果
List<Object> values = st.values();
for (int i = 0; i < values.size(); i++) {
Object value = values.get(i);
if (value instanceof List<?> list) {
sb.append(String.join(", ", list.stream()
.map(Object::toString)
.toList()));
} else {
sb.append(value);
}
if (i < st.fragments().size() - 1) {
sb.append(st.fragments().get(i + 1));
}
}
return sb.toString();
};
public static void main(String[] args) {
basicStringTemplate();
sqlTemplateDemo();
customProcessorDemo();
}
}字符串模板的主要优势:
+拼接或String.format(),字符串模板更接近最终的字符串形式,可读性更好。"""包裹的多行模板保留了换行和缩进,非常适合生成 HTML、XML 等多行文本。JDK 25 提供了几个内置处理器:
STR:基本字符串拼接处理器FMT:支持格式说明符(如%d、%s)的格式化处理器RAW:返回未处理的字符串模板对象,用于自定义处理SQL:用于 SQL 语句生成的安全处理器JDK 25 对开关表达式进行了进一步增强,使其更加灵活和强大:
package com.example.jdk25.feature;
import lombok.extern.slf4j.Slf4j;
import java.time.DayOfWeek;
/**
* 开关表达式增强演示
*
* @author ken
*/
@Slf4j
public class SwitchExpressionsDemo {
/**
* 演示case标签中的表达式
*
* @param number 输入数字
* @return 数字分类
*/
public static String classifyNumber(int number) {
return switch (number) {
case 0 -> "Zero";
case 1, 3, 5, 7, 9 -> "Odd";
case 2, 4, 6, 8 -> "Even";
case Integer.MIN_VALUE -> "Minimum value";
case Integer.MAX_VALUE -> "Maximum value";
default -> "Other number";
};
}
/**
* 演示模式匹配的switch
*
* @param obj 输入对象
* @return 对象类型描述
*/
public static String describeObject(Object obj) {
return switch (obj) {
case null -> "Null";
case String s -> "String with length: " + s.length();
case Integer i -> "Integer: " + i;
case Double d -> "Double: " + d;
case DayOfWeek d -> "Day of week: " + d;
default -> "Unknown type: " + obj.getClass().getSimpleName();
};
}
/**
* 演示基于范围的switch
*
* @param score 分数
* @return 等级
*/
public static String getGrade(int score) {
return switch (score) {
case int s when s >= 90 -> "A";
case int s when s >= 80 -> "B";
case int s when s >= 70 -> "C";
case int s when s >= 60 -> "D";
case int s when s >= 0 -> "F";
default -> "Invalid score";
};
}
public static void main(String[] args) {
log.info("Classify 5: {}", classifyNumber(5));
log.info("Classify 8: {}", classifyNumber(8));
log.info("Classify max value: {}", classifyNumber(Integer.MAX_VALUE));
log.info("Describe \"hello\": {}", describeObject("hello"));
log.info("Describe 42: {}", describeObject(42));
log.info("Describe DayOfWeek.MONDAY: {}", describeObject(DayOfWeek.MONDAY));
log.info("Grade for 85: {}", getGrade(85));
log.info("Grade for 62: {}", getGrade(62));
}
}这些增强使得 switch 表达式在处理复杂条件时更加灵活,代码更加简洁。特别是结合模式匹配和 when 子句,能够处理以前需要多个 if-else 语句才能完成的逻辑。
ZGC(Z Garbage Collector)是 Java 中一款低延迟垃圾收集器,自 JDK 11 引入以来备受关注。JDK 25 通过 JEP 439 正式引入了分代 ZGC,进一步提升了其性能。
分代 ZGC 基于 "大多数对象很快会变得不可达" 的观察,将对象分为年轻代和老年代,对不同代采用不同的收集策略:

分代 ZGC 的主要优势:
要启用分代 ZGC,需要在启动参数中指定:
java -XX:+UseZGC -XX:+ZGenerational -jar your-application.jarJDK 25 还引入了一些新的 ZGC 相关 JVM 参数,用于调优分代收集行为:
-XX:ZYoungGenerationSize:设置年轻代的初始大小-XX:ZYoungGenerationSizeMin:年轻代的最小大小-XX:ZYoungGenerationSizeMax:年轻代的最大大小-XX:ZTenuringThreshold:对象晋升到老年代的存活次数阈值经过多个孵化和预览阶段,向量 API 终于在 JDK 25 中成为正式特性。向量 API 允许开发者编写可移植的、高性能的向量计算代码,充分利用现代 CPU 的 SIMD(单指令多数据)指令集。
向量计算可以同时对多个数据元素执行相同的操作,非常适合科学计算、机器学习、图像处理等场景。
package com.example.jdk25.feature;
import lombok.extern.slf4j.Slf4j;
import jdk.incubator.vector.*;
import java.util.Arrays;
/**
* 向量API演示
*
* @author ken
*/
@Slf4j
public class VectorApiDemo {
/**
* 向量长度:根据CPU架构自动选择最佳长度
*/
private static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;
/**
* 使用向量API进行数组加法
*
* @param a 第一个数组
* @param b 第二个数组
* @return 结果数组
*/
public static float[] vectorAdd(float[] a, float[] b) {
// 校验输入
if (a.length != b.length) {
throw new IllegalArgumentException("数组长度必须相等");
}
int length = a.length;
float[] result = new float[length];
int i = 0;
// 向量计算部分
int upperBound = SPECIES.loopBound(length);
for (; i < upperBound; i += SPECIES.length()) {
// 从数组加载向量
FloatVector va = FloatVector.fromArray(SPECIES, a, i);
FloatVector vb = FloatVector.fromArray(SPECIES, b, i);
// 执行向量加法并存储结果
FloatVector vc = va.add(vb);
vc.intoArray(result, i);
}
// 处理剩余元素
for (; i < length; i++) {
result[i] = a[i] + b[i];
}
return result;
}
/**
* 传统数组加法
*
* @param a 第一个数组
* @param b 第二个数组
* @return 结果数组
*/
public static float[] scalarAdd(float[] a, float[] b) {
if (a.length != b.length) {
throw new IllegalArgumentException("数组长度必须相等");
}
int length = a.length;
float[] result = new float[length];
for (int i = 0; i < length; i++) {
result[i] = a[i] + b[i];
}
return result;
}
public static void main(String[] args) {
// 创建测试数据
int size = 1_000_000;
float[] a = new float[size];
float[] b = new float[size];
for (int i = 0; i < size; i++) {
a[i] = (float) Math.random();
b[i] = (float) Math.random();
}
// 验证向量计算正确性
float[] vectorResult = vectorAdd(a, b);
float[] scalarResult = scalarAdd(a, b);
log.info("计算结果是否一致: {}", Arrays.equals(vectorResult, scalarResult));
// 性能测试
long start = System.nanoTime();
for (int i = 0; i < 100; i++) {
vectorAdd(a, b);
}
long vectorTime = System.nanoTime() - start;
start = System.nanoTime();
for (int i = 0; i < 100; i++) {
scalarAdd(a, b);
}
long scalarTime = System.nanoTime() - start;
log.info("向量计算总时间: {} ms", vectorTime / 1_000_000);
log.info("标量计算总时间: {} ms", scalarTime / 1_000_000);
log.info("向量计算速度提升: {}%", (1 - (double) vectorTime / scalarTime) * 100);
}
}向量 API 的主要优势:
在实际测试中,向量 API 在数值计算密集型任务中通常能带来 2-8 倍的性能提升,具体取决于任务类型和 CPU 架构。
虚拟线程是 JDK 19 中引入的预览特性,在 JDK 25 中得到了进一步优化和稳定。虚拟线程是轻量级线程,由 JVM 管理而非操作系统,能够显著提高高并发场景下的性能和资源利用率。
JDK 25 对虚拟线程的优化主要包括:
package com.example.jdk25.feature;
import lombok.extern.slf4j.Slf4j;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 虚拟线程优化演示
*
* @author ken
*/
@Slf4j
public class VirtualThreadsDemo {
/**
* 模拟一个I/O密集型任务
*
* @param taskId 任务ID
*/
public static void ioBoundTask(int taskId) {
try {
// 模拟I/O操作等待
Thread.sleep(Duration.ofMillis(100));
log.debug("任务 {} 完成", taskId);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("任务 {} 被中断", taskId, e);
}
}
/**
* 使用虚拟线程执行大量I/O密集型任务
*
* @param taskCount 任务数量
*/
public static void runWithVirtualThreads(int taskCount) throws InterruptedException {
long startTime = System.currentTimeMillis();
// 创建虚拟线程池
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < taskCount; i++) {
int taskId = i;
executor.submit(() -> ioBoundTask(taskId));
}
}
long endTime = System.currentTimeMillis();
log.info("虚拟线程执行 {} 个任务耗时: {} ms", taskCount, endTime - startTime);
}
/**
* 使用平台线程执行大量I/O密集型任务
*
* @param taskCount 任务数量
*/
public static void runWithPlatformThreads(int taskCount) throws InterruptedException {
long startTime = System.currentTimeMillis();
// 创建固定大小的平台线程池
try (ExecutorService executor = Executors.newFixedThreadPool(100)) {
for (int i = 0; i < taskCount; i++) {
int taskId = i;
executor.submit(() -> ioBoundTask(taskId));
}
}
long endTime = System.currentTimeMillis();
log.info("平台线程执行 {} 个任务耗时: {} ms", taskCount, endTime - startTime);
}
public static void main(String[] args) throws InterruptedException {
int taskCount = 10_000;
// 先预热
runWithVirtualThreads(1000);
runWithPlatformThreads(1000);
// 正式测试
runWithVirtualThreads(taskCount);
runWithPlatformThreads(taskCount);
}
}
虚拟线程特别适合处理 I/O 密集型任务,如 Web 服务、数据库访问、网络请求等。在这些场景中,线程大部分时间都在等待 I/O 操作完成,而不是进行 CPU 计算。
JDK 25 中虚拟线程的优化使得它们在以下方面表现更佳:
在实际应用中,使用虚拟线程可以显著提高系统的并发处理能力,同时降低资源消耗。
JDK 25 对集合框架进行了多项实用增强,主要包括:
List.ofEntries()、Map.ofEntries()等,方便从其他集合或条目创建新集合。List.subList()、Map.keySet()等视图支持更多操作。package com.example.jdk25.feature;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
* 集合框架增强演示
*
* @author ken
*/
@Slf4j
public class CollectionsEnhancementsDemo {
/**
* 演示新的集合工厂方法
*/
public static void demoFactoryMethods() {
// 从条目创建列表
List<String> listFromEntries = List.ofEntries(
Map.entry(0, "zero"),
Map.entry(2, "two"),
Map.entry(1, "one")
).stream()
.map(Map.Entry::getValue)
.collect(Collectors.toList());
log.info("从条目创建的列表: {}", listFromEntries);
// 从其他集合创建不可变映射
Map<String, Integer> mutableMap = new HashMap<>();
mutableMap.put("apple", 1);
mutableMap.put("banana", 2);
Map<String, Integer> immutableMap = Map.copyOfEntries(mutableMap.entrySet());
log.info("从条目复制的不可变映射: {}", immutableMap);
// 尝试修改不可变映射会抛出异常
try {
immutableMap.put("cherry", 3);
} catch (UnsupportedOperationException e) {
log.info("正确捕获了修改不可变映射的异常");
}
}
/**
* 演示集合视图增强
*/
public static void demoViewEnhancements() {
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
// 键集视图现在支持更多操作
Set<String> keySet = map.keySet();
log.info("原始键集: {}", keySet);
// 移除满足条件的元素
keySet.removeIf(key -> key.equals("b"));
log.info("移除'b'后的键集: {}", keySet);
log.info("对应的映射: {}", map);
// 列表子视图增强
List<String> list = new ArrayList<>(List.of("a", "b", "c", "d", "e"));
List<String> subList = list.subList(1, 4);
log.info("原始子列表: {}", subList);
// 对子列表进行排序
subList.sort(Collections.reverseOrder());
log.info("排序后的子列表: {}", subList);
log.info("原始列表也随之改变: {}", list);
}
/**
* 演示集合排序增强
*/
public static void demoSortingEnhancements() {
List<String> words = new ArrayList<>(List.of("banana", "apple", "cherry", "date"));
// 使用新的排序方法
words.sort(String::compareToIgnoreCase);
log.info("忽略大小写排序: {}", words);
// 按长度排序,长度相同则按字母顺序
words.sort(Comparator.comparingInt(String::length)
.thenComparing(String::compareTo));
log.info("按长度和字母排序: {}", words);
// 反向排序
words.sort(Comparator.reverseOrder());
log.info("反向排序: {}", words);
}
public static void main(String[] args) {
demoFactoryMethods();
demoViewEnhancements();
demoSortingEnhancements();
}
}这些增强使得集合操作更加简洁高效,特别是在创建不可变集合和处理集合视图时,减少了许多模板代码。
JDK 25 对日期时间 API(java.time)进行了多项实用扩展,主要包括:
package com.example.jdk25.feature;
import lombok.extern.slf4j.Slf4j;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Locale;
/**
* 日期时间API扩展演示
*
* @author ken
*/
@Slf4j
public class DateTimeApiEnhancementsDemo {
/**
* 演示新的日期时间格式化功能
*/
public static void demoFormatting() {
LocalDateTime now = LocalDateTime.now();
// 新的格式化模式
DateTimeFormatter shortFormatter = DateTimeFormatter.ofLocalizedDateTime(
FormatStyle.SHORT, FormatStyle.MEDIUM);
DateTimeFormatter longFormatter = DateTimeFormatter.ofLocalizedDateTime(
FormatStyle.LONG, FormatStyle.LONG);
log.info("简短格式: {}", now.format(shortFormatter));
log.info("长格式: {}", now.format(longFormatter));
// 支持更多本地化格式
Locale french = Locale.FRENCH;
Locale japanese = Locale.JAPANESE;
log.info("法语格式: {}", now.format(DateTimeFormatter.ofLocalizedDateTime(
FormatStyle.FULL).withLocale(french)));
log.info("日语格式: {}", now.format(DateTimeFormatter.ofLocalizedDateTime(
FormatStyle.FULL).withLocale(japanese)));
// 新的自定义模式字符
DateTimeFormatter weekFormatter = DateTimeFormatter.ofPattern("yyyy-'W'ww-u");
log.info("周格式 (年-W周数-星期几): {}", now.format(weekFormatter));
}
/**
* 演示增强的日期计算功能
*/
public static void demoDateCalculations() {
LocalDate today = LocalDate.now();
log.info("今天: {}", today);
// 计算下一个工作日(跳过周末)
LocalDate nextWorkday = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY));
log.info("下一个工作日: {}", nextWorkday);
// 计算两个日期之间的工作日天数
LocalDate futureDate = today.plus(2, ChronoUnit.WEEKS);
long workdays = ChronoUnit.DAYS.between(today, futureDate) -
2 * (ChronoUnit.WEEKS.between(today, futureDate));
log.info("从今天到 {} 的工作日天数: {}", futureDate, workdays);
// 计算相对日期
LocalDate payday = today.with(TemporalAdjusters.lastDayOfMonth());
if (payday.getDayOfWeek() == DayOfWeek.SATURDAY) {
payday = payday.minusDays(1);
} else if (payday.getDayOfWeek() == DayOfWeek.SUNDAY) {
payday = payday.minusDays(2);
}
log.info("本月发薪日: {}", payday);
}
/**
* 演示时区处理优化
*/
public static void demoTimeZoneHandling() {
Instant now = Instant.now();
log.info("当前时刻: {}", now);
// 时区转换
ZonedDateTime newYorkTime = now.atZone(ZoneId.of("America/New_York"));
ZonedDateTime londonTime = now.atZone(ZoneId.of("Europe/London"));
ZonedDateTime shanghaiTime = now.atZone(ZoneId.of("Asia/Shanghai"));
log.info("纽约时间: {}", newYorkTime);
log.info("伦敦时间: {}", londonTime);
log.info("上海时间: {}", shanghaiTime);
// 夏令时处理优化
ZonedDateTime nySummer = ZonedDateTime.of(
2024, 6, 1, 12, 0, 0, 0,
ZoneId.of("America/New_York")
);
ZonedDateTime nyWinter = ZonedDateTime.of(
2024, 12, 1, 12, 0, 0, 0,
ZoneId.of("America/New_York")
);
log.info("纽约夏季时间 (UTC偏移): {}", nySummer);
log.info("纽约冬季时间 (UTC偏移): {}", nyWinter);
}
public static void main(String[] args) {
demoFormatting();
demoDateCalculations();
demoTimeZoneHandling();
}
}这些增强使得日期时间处理更加灵活和直观,特别是在处理国际化应用和复杂日期计算时,减少了许多手动处理的需要。
JDK 11 引入的 HttpClient 在 JDK 25 中得到了进一步增强,主要包括:
package com.example.jdk25.feature;
import lombok.extern.slf4j.Slf4j;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.WebSocket;
import java.time.Duration;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.CountDownLatch;
/**
* HTTP客户端改进演示
*
* @author ken
*/
@Slf4j
public class HttpClientEnhancementsDemo {
private static final String API_URL = "https://api.example.com/data";
private static final String WS_URL = "wss://ws.example.com/updates";
/**
* 演示HTTP客户端的基本用法和增强
*/
public static void demoHttpClient() throws Exception {
// 创建HTTP客户端,配置超时和版本
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.version(HttpClient.Version.HTTP_2)
.build();
// 创建HTTP请求
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(API_URL))
.timeout(Duration.ofSeconds(5))
.header("Accept", "application/json")
.GET()
.build();
// 发送同步请求
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
log.info("同步请求状态码: {}", response.statusCode());
log.info("同步请求响应长度: {}", response.body().length());
// 发送异步请求
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(body -> log.info("异步请求响应长度: {}", body.length()))
.exceptionally(ex -> {
log.error("异步请求出错", ex);
return null;
})
.join();
}
/**
* 演示WebSocket增强功能
*/
public static void demoWebSocket() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
// 创建WebSocket客户端
WebSocket webSocket = HttpClient.newHttpClient()
.newWebSocketBuilder()
.buildAsync(URI.create(WS_URL), new WebSocket.Listener() {
@Override
public void onOpen(WebSocket webSocket) {
log.info("WebSocket连接已打开");
webSocket.request(1);
// 发送消息
webSocket.sendText("Hello, Server!", true)
.thenRun(() -> log.info("客户端消息已发送"))
.exceptionally(ex -> {
log.error("发送消息出错", ex);
return null;
});
}
@Override
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
log.info("收到服务器消息: {}", data);
webSocket.request(1);
// 如果收到关闭消息,则关闭连接
if (data.toString().contains("close")) {
return webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "Done")
.thenRun(latch::countDown);
}
return CompletionStage.completedFuture(null);
}
@Override
public void onError(WebSocket webSocket, Throwable error) {
log.error("WebSocket错误", error);
latch.countDown();
}
@Override
public CompletionStage<?> onClose(WebSocket webSocket, int statusCode, String reason) {
log.info("WebSocket已关闭: {} - {}", statusCode, reason);
latch.countDown();
return CompletionStage.completedFuture(null);
}
})
.join();
// 等待WebSocket交互完成
latch.await(10, java.util.concurrent.TimeUnit.SECONDS);
webSocket.abort();
}
public static void main(String[] args) throws Exception {
demoHttpClient();
demoWebSocket();
}
}JDK 25 中的 HttpClient 增强使得它在处理现代 Web 服务和实时通信时更加得心应手,性能和功能都有显著提升。对于大多数应用场景,JDK 内置的 HttpClient 已经可以替代第三方库如 Apache HttpClient 或 OkHttp。
Java Flight Recorder 是一款低开销的诊断工具,JDK 25 对其进行了多项增强:
package com.example.jdk25.feature;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import lombok.extern.slf4j.Slf4j;
/**
* JFR增强演示
*
* @author ken
*/
@Slf4j
public class JfrEnhancementsDemo {
/**
* 自定义JFR事件:订单处理事件
*/
@Label("Order Processing")
@Description("记录订单处理的详细信息")
@Category({"Business", "Orders"})
public static class OrderProcessingEvent extends Event {
@Label("Order ID")
private final String orderId;
@Label("Customer ID")
private final String customerId;
@Label("Processing Time (ms)")
private final long processingTime;
@Label("Order Amount")
private final double amount;
public OrderProcessingEvent(String orderId, String customerId,
long processingTime, double amount) {
this.orderId = orderId;
this.customerId = customerId;
this.processingTime = processingTime;
this.amount = amount;
}
}
/**
* 模拟订单处理
*
* @param orderId 订单ID
* @param customerId 客户ID
* @param amount 订单金额
*/
public static void processOrder(String orderId, String customerId, double amount) {
long startTime = System.currentTimeMillis();
// 模拟订单处理
try {
Thread.sleep((long) (Math.random() * 100));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
long processingTime = System.currentTimeMillis() - startTime;
// 记录JFR事件
OrderProcessingEvent event = new OrderProcessingEvent(
orderId, customerId, processingTime, amount);
event.commit();
log.info("订单 {} 处理完成,耗时 {} ms", orderId, processingTime);
}
public static void main(String[] args) {
log.info("开始处理订单...");
// 处理一批订单
for (int i = 0; i < 100; i++) {
processOrder(
"ORD-" + System.currentTimeMillis() + "-" + i,
"CUST-" + (i % 10),
100 + Math.random() * 900
);
}
log.info("所有订单处理完成");
log.info("使用JDK Mission Control查看JFR记录的事件");
}
}要启用 JFR 并记录事件,可以使用以下命令:
# 启动应用并开始JFR记录
java -XX:StartFlightRecording=duration=60s,filename=order-processing.jfr \
-jar your-application.jar
# 应用运行中开始JFR记录
jcmd <pid> JFR.start duration=60s filename=recording.jfr
# 停止JFR记录
jcmd <pid> JFR.stopJDK 25 中 JFR 的增强使其成为诊断生产环境问题的更强大工具,低开销特性意味着可以在不影响应用性能的情况下长期启用。
jlink 是用于创建自定义 JRE 镜像的工具,JDK 25 对其进行了多项改进:
使用 jlink 创建优化的 JRE 镜像:
# 基本用法:创建包含特定模块的JRE镜像
jlink --module-path $JAVA_HOME/jmods \
--add-modules java.base,java.logging,java.net.http \
--output myjre \
--strip-debug \
--compress 2 \
--no-man-pages \
--no-header-files
# 高级用法:使用优化插件
jlink --module-path $JAVA_HOME/jmods \
--add-modules java.base,java.sql,java.xml \
--output optimized-jre \
--strip-debug \
--compress 2 \
--plugin compress-strings \
--plugin optimize-reflection \
--plugin jni-optimize
JDK 25 中 jlink 的改进使得创建定制化 JRE 更加灵活高效,生成的镜像体积更小、启动更快,非常适合容器化部署和资源受限的环境。
迁移到 JDK 25 通常是一个平滑的过程,但仍需注意以下几点:
Thread.stop()、sun.misc包中的部分类等,需要替换为推荐的替代方案。module-info.java文件。Maven 配置示例:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>25</source>
<target>25</target>
<release>25</release>
<compilerArgs>
<!-- 启用预览特性(如果需要) -->
<!--<arg>--enable-preview</arg>-->
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
Executors.newVirtualThreadPerTaskExecutor()创建虚拟线程池-XX:+UseZGC -XX:+ZGenerational+拼接或String.format()JDK 25 作为一个非 LTS 版本,带来了多项令人兴奋的新特性和改进,涵盖了语言特性、JVM 优化、核心库增强和工具改进等多个方面。从模式匹配的进一步增强到字符串模板的正式转正,从分代 ZGC 的性能提升到向量 API 的正式发布,每一项更新都旨在让 Java 开发者能够编写更简洁、更高效、更安全的代码。
特别值得关注的是,JDK 25 继续推进了 Java 向现代编程语言的演进,通过引入更多函数式编程特性和简化代码的语法糖,使 Java 在保持稳定性和兼容性的同时,也能跟上编程语言的发展潮流。
对于企业应用开发者来说,JDK 25 中的虚拟线程优化和分代 ZGC 将带来显著的性能提升,尤其是在高并发和大数据处理场景。而字符串模板和模式匹配的增强则将大大提高开发效率和代码可读性。