我有很多具有 ZoneId tz
字段的对象。
tz
字段的所有实例都是通过 ZoneId.of
静态方法创建的。
我最初选择 ZoneId
而不是普通的 String
是因为期望 ZoneId
实例将被缓存(因为时区集有限)。然而,在分析堆之后我发现事实并非如此:
每次使用相同参数调用 ZoneId.of
都会创建一个 ZoneRegion
的新实例:
ZoneId zoneId1 = ZoneId.of("Europe/Kiev"); //allocates new ZoneRegion
ZoneId zoneId2 = ZoneId.of("Europe/Kiev"); //allocates new ZoneRegion
我的问题是 - 这是预期的还是这是某种 JVM 错误?
openjdk version "21.0.1" 2023-10-17
OpenJDK Runtime Environment (build 21.0.1+12-Ubuntu-222.04)
OpenJDK 64-Bit Server VM (build 21.0.1+12-Ubuntu-222.04, mixed mode, sharing)
最佳答案
My question is - is that expected or this is some kind of JVM bug?
检查最新的 javadoc (JDK22u),没有提到“这些值是单例”。因为我们可以更简单地陈述您的情况,而不会引入堆问题:
// bug claim:
ZoneId a = ZoneId.of("Europe/Kiev");
ZoneId b = ZoneId.of("Europe/Kiev");
System.out.println(a == b); // should print true!
...但是这会打印false
,因此这意味着驱动ZoneId.of
的机制不会导致单例 ZoneId
对象 - 要么 JDK 不存在预缓存每个可能的 ZoneId 对象,要么 ZoneId.of 本身无法建立缓存。
or this is some kind of JVM bug?
好吧,Java Lang 规范和 Java 虚拟机规范不会(或不应该)提及任何有关此的内容,因为它不在 java.lang
包或子包中,这就是对语言本身至关重要的任何类型都需要在 JLS/JVMS 中提及的地方。
因此,javadoc 是规范的规范来源。
ZoneId
在 javadoc 中的任何地方都没有提到它们是单例,ZoneId.of
也没有提到这一点。
仅供引用,current JDK22u sources of ZoneId .
有一行:
* The ID is unique within the system.
关于 ZoneId 本身,可能解释为:这里的“ID”是“ZoneId 的实例”的缩写,但这并不是对该行的明显解释;他们正在谈论的是例如Europe/Kiev
作为一个概念,不能导致同时指代哪个时区的两种不同概念。文档的这一部分与“...并且系统应缓存此概念以便不需要存在两个实例”的实现细节级别概念无关。
它确实包含一个附加条件,即实例将被视为 ValueBased(在主 javadoc 的末尾):您不应该以任何方式做出假设,例如==
就可以(换句话说,他们明确保留引入某种缓存机制的权利,或者这些将成为直接的 valhalla 风格值类,没有 首先是一个身份)。但这只是规定您不应该依赖任何一个:您不能依赖重复调用 ZoneId.of("Europe/Kiev")
返回不同的对象,您也不能依赖此类调用返回相同的对象。从代码角度来看,您根本不应该考虑对象的 ZoneId 实例。
解决方案
如果您的探查器报告强烈建议减少 ZoneId 实例的数量会有所帮助,那么 API 文档将授予您缓存这些实例的权利:
private static final Map<String, ZoneId> CACHED_ZONE_IDS = new HashMap<>();
public static ZoneId cachedOf(String id) {
return CACHED_ZONE_IDS.computeIfAbsent(id, ZoneId::of);
}
如果您担心需要“超时”缓存 map 中不再有效使用的 ZoneId,您可以查看 guava 的 CacheBuilder,但这似乎有点矫枉过正;我将其保留为上面的 3 行短代码。
关于java - Java 堆中存在许多 java.time.ZoneRegion 实例。难道 ZoneId 实例不应该被缓存吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77660349/