Skip to content

性能优化-升级JDK

About 1330 wordsAbout 4 min

性能新书

2026-08-21

5.10 升级JDK

Java每个版本迭代,除了新的语言特性外,还有安全提升,JVM和SDK的性能提升,比如JDK7之前生成随机函数是Random类,多线程下使用单个Random实例生成随机数时候,多个线程同时计算随机数计算新的种子时候多个线程会竞争同一个原子变量的更新操作,由于原子变量的更新是CAS操作,同时只有一个线程会成功,所以会造成大量线程进行自旋重试,这是会降低并发性能的,JDK7增加了ThreadLocalRandom,有更好的性能

可以运行RandomTest比较俩着的性能,RandomTest使用50个并发线程测试

  @BenchmarkMode(Mode.AverageTime)
  @Warmup(iterations = 5)
  @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
  @Threads(50)
  @Fork(1)
  @OutputTimeUnit(TimeUnit.NANOSECONDS)
  @State(Scope.Benchmark)
  public class RandomTest {
    Random random = new Random();
    @Benchmark
    public int random() {
      return random.nextInt(50);
    }

    @Benchmark
    public int localRandom() {
      ThreadLocalRandom random = ThreadLocalRandom.current();
      return random.nextInt(50);
    }
  }

从测试结果来看,ThreadLocalRandom性能远远超过Random

Benchmark                         Mode     Score    Units         
c.i.c.c.RandomTest.localRandom    avgt   109.176    ns/op         
c.i.c.c.RandomTest.random         avgt  7137.961    ns/op

Java每次升级都有较多的性能改,下表列出了我在项目中遇到有显著性能提升的升级

API描述新版本性能提升
Random生成随机函数JDK8,采用ThreadLocalRandom7000%
DateFomart日期格式化JDK8, 采用DateTimeFormatter300%
SSLEngineSSL握手,用于网络安全认证JDK8最新版本,优化加密解密计算,预分配了缓存用于存放解码内容200%
BASE64Encoder二进制和Base64编解码JDK8使用java.util.Base64500%
String字符串拼接JDK9 不再编译时期调用StringBuilder,改成了在运行时期根据拼接内容动态决定如何拼接略有提升
HTTP ClientHTTP客户端JDK17有较大性能提升,之前则采用第三方的,如Apache Client或者HttpOK略有提升
线程JDK的Thread映射成内核线程pthread,上下文切换开销较大。Java21 实现虚拟线程,虚拟线程是由JVM管理的轻量级线程。虚拟线程非常适合I/O密集型任务或需要大量并行性的任务。单个JVM可以创建数百万的虚拟线程

如下是使用虚拟线程,可以轻松创建数十万的并发计算任务

Runnable runnable = () -> {
   //完成某些计算
};

try (ExecutorService pool = Executors.newVirtualThreadPerTaskExecutor()) {
    for (int i = 0; i < 1000000; i++) {
        pool.submit(runnable);
    }
}

下表列出了JEP 提案中提到的Java各个版本的性能优化,数据来源JEP官网,并使用AI总结成如下表格。JEP主要是对JVM,JIT,并发,以及标准库的性能优化。

LTS版本GA 时间核心性能主线
LTS82014-03并行 GC 吞吐基线、压缩指针
92017-09GC 默认切换 G1 + 内存****减半(紧凑字符串)
102018-03G1 Full GC 并行化
LTS112018-09低延迟 GC 入局(ZGC/Epsilon)+ JFR 开源
122019-03Shenandoah + 默认 CDS
132019-09动态 CDS + ZGC 内存归还
142020-03ZGC 生产级、G1 NUMA、移除 CMS
152020-09ZGC/Shenandoah 转正
162021-03弹性元空间 + ZGC 并发栈
LTS172021-09清理(移除 AOT/Graal)、PRNG 增强
182022-03夯实期(UTF-8 默认等)
192022-09并发范式转折点:虚拟线程预览
202023-03演进期
LTS212023-09分代 ZGC + 虚拟线程转正
222024-03FFM 转正、G1 区域钉扎
232024-09ZGC 分代默认
242025-03虚拟线程去钉扎 + 紧凑对象头 + AOT 类加载

以Java8为例子,优化了GC、内存使用和标准库

GC 与****内存

机制要点
默认并行收集器Parallel Scavenge(新生代) + Parallel Old(老年代),多线程并行 STW吞吐优先;停顿随堆增长恶化
压缩指针-XX:+UseCompressedOops(64 位默认)引用 8B→4B,堆<32G 时内存与缓存均受益
8u131/8u191 容器感知-XX:+UseContainerSupport(8u191 默认)容器内正确识别 CPU/内存配额,避免 OOM

标准库

机制要点
JEP 192 字符串去重(8u20)G1 下 -XX:+UseStringDeduplication:重复 String 共享底层 char[]显式开启;适合字符串驻留多的应用
Lambda/Stream集合管道化编码间接:减少手写循环开销,便于 JIT 优化

以Java21 为例子,优化了GC和并发

GC

机制收益
JEP 439 分代 ZGC年轻/老年代分离,小堆(≤16G)收益最大吞吐≈G1,停顿亚毫秒(官方:相比非分代 ZGC 吞吐提升 2~4 倍量级)

并发

机制收益
JEP 444 虚拟线程转正生产可用百万级线程(官方 demo 100 万虚拟线程);I/O 密集应用吞吐提升数倍至一个数量级

注意:升级JDK版本有风险,需要充分的测试。尤其是跟安全相关的功能,JDK可能因为安全原因不再与旧版本兼容,如JDK每次大版本更新,一些被认为不安全的加密算法就会下线。如果客户端依然使用老的加加密算法,可能导致客户端访问失败

JDK升级有可能意味着 框架或者工具库可能不兼容,比如JDK17不再支持java.ee包,改成了jakarta.ee,必须同步升级开发框架和依赖的工具,这可能进一步引入新的风险

知行合一