升级JDK
上周日上午碰到了一个有意思的问题:生产环境上为一个用户安排定时任务的时候报错,扔出来的堆栈报错信息如下:
Unexpected error occurred in scheduled task
java.time.zone.ZoneRulesException: Unknown time-zone ID: America/Nuuk
at java.time.zone.ZoneRulesProvider.getProvider(ZoneRulesProvider.java:272)
at java.time.zone.ZoneRulesProvider.getRules(ZoneRulesProvider.java:227)
at java.time.ZoneRegion.ofId(ZoneRegion.java:120)
at java.time.ZoneId.of(ZoneId.java:411)
at java.time.ZoneId.of(ZoneId.java:359)
比较有意思的是这个时区:America/Nuuk
按理来说,在JDK层面应该不会有这种错误,第一想法就是去查这个时区存不存在,结果是有这么个时区的:

还是格陵兰的用户…
记得格陵兰的用户也不少,为什么之前没有这个问题?于是去翻了一下Wikipedia的tzdata列表,下面有一栏写着:
GL | +6411-05144 | America/Godthab | Deprecated | -03:00 | -02:00 | Link to America/Nuuk |
---|
时区这东西还能Deprecated啊…
看了一下America/Godthab词条,直接跳到了另一个条目,里面也没写明为什么要换,即使是tzdata2020a的版本变化也没有说明白,只是简单的说了:
To reflect current usage in English better, America/Godthab has been renamed to America/Nuuk. A backwards-compatibility link remains for the old name.
好家伙
看了一眼线上用的jdk版本是8u232,还是2019年10月15日的版本,找到了支持tzdata2020a的补丁提交:[JDK-8243541] (tz) Upgrade time-zone data to tzdata2020a - Java Bug System:
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8244039 | 8u271 | Kiran Sidhartha Ravikumar | P3 | Resolved | Fixed | b01 |
JDK-8244849 | 8u261 | Kiran Sidhartha Ravikumar | P3 | Resolved | Fixed | b07 |
JDK-8244950 | 8u260 | Kiran Sidhartha Ravikumar | P3 | Resolved | Fixed | master |
为了确定新的JDK Update能够支持,我在自己机器上用8u292跑了一下这个代码:
LocalDateTime now = LocalDateTime.now();
ZonedDateTime deviceTime = now.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("America/Nuuk"));
System.out.println(deviceTime);
输出正常:
2021-08-16T12:40:52.385-02:00[America/Nuuk]
而换成和生产一致的8u232,则会抛出和最上面一致的出错信息
今天把生产上的Docker Image全换成8u292的之后,回来想了一下,让我主动升级JDK的还有8u162,这个版本把crypto的加密算法Key长度限制放开了。虽在之前用BouncyCastle特殊的AP绕过了这些条条框框,但也免不了后来人用BouncyCastle的JCE实现,本地环境没问题,上生产环境启动直接报错。
Java 8也用了6年,下个月应该要准备上Java 17了