微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java/ColdFusion 和 Lucee 之间的 identityHashCode 区别

如何解决Java/ColdFusion 和 Lucee 之间的 identityHashCode 区别

编辑:Bug has been filed.

假设我有两个相互指向的 ArrayList(循环引用):

x = createObject("java","java.util.ArrayList").init();
y = createObject("java","java.util.ArrayList").init();
x.add(y);
y.add(x);

如果我对它们中的任何一个调用 hashCode,它会导致 StackOverflowError due to the ArrayList implementation。这是意料之中的。

但是,当我调用 System.identityHashCode 时,是不是应该使用 Object.hashCode 实现,它不会跟随 ArrayList 中的元素,因此不会导致 {{1} }?

Documentation of identityHashCode 声明:

为给定的对象返回与返回的相同的哈希码 通过方法 hashCode(),无论给定对象的 类覆盖 hashCode()。

在 Adob​​e ColdFusion 中,此代码工作正常:

StackOverflowError

(这显然也适用于本地编译并使用 Java 运行。)

然而,在 lucee 中,它会立即导致 System = createObject("java","java.lang.System"); System.identityHashCode(x); // returns some integer System.identityHashCode(y); // returns another integer

StackOverflowError

为什么它在这里运行 lucee.runtime.exp.NativeException: java.lang.StackOverflowError at java.base/java.util.ArrayList.hashCodeRange(ArrayList.java:627) at java.base/java.util.ArrayList.hashCode(ArrayList.java:614) at java.base/java.util.ArrayList.hashCodeRange(ArrayList.java:627) at java.base/java.util.ArrayList.hashCode(ArrayList.java:614) [...] 的 ArrayList 实现?

两个 CFML 引擎都在同一个 servlet (Tomcat 9) 上运行相同的 JVM (HotSpot) 和 Java 版本 (11)。我想了解为什么他们的行为不同。

解决方法

System.identityHashCode 的实现是 native - 它是在 VM 级别实现的;这不是java代码。 iHC 的规范故意含糊不清。

它含糊不清的原因是因为它高度依赖于平台,并且规范试图为在异国平台上的虚拟机实现者提供足够的余地(ColdFusion 和 Lucee 当然很重要,不是吗?)来制作符合规范的 impl。

Object 的 hashCode impl 技术上可以扫描字段,尽管这会非常低效(因为 System.iHC 在需要快速响应的地方被大量使用,而这绝不是),并且您不是唯一一个假设 System.iHC 不会永远循环的人,即使在(最终)引用自身的对象中也是如此。

但是,关键是,那些被广泛使用的假设;该方法的规范中没有任何内容表明它是这样工作的。

另一方面,Lucee 所采取的回旋余地(如果你说的确实是真的)是相当过分的。

因此,您现在被困住了。这些都是真的:

  • 大量代码假设 iHC 无法循环。因此,事实上,VM 实现会循环是非常不切实际的。
  • 大量代码都假设 iHC 速度很快。因此,事实上,VM 实现会很慢是非常不切实际的。
  • 尽管如此,Lucee 可以走“我是橡胶,你是胶水,无论你的错误报告从我身上反弹并坚持你”的路线,并告诉你他们的 impl 根据规范是有效的,因此无论代码你愿意折腾他们来表明你的观点是错误的。

但先给他们一个机会,在你认为他们会打开门之前,嗯!不是我们的错!技术上可供他们使用的路线。

如果他们拒绝了您的错误报告,和/或您想在将其提交给他们的错误跟踪器之前对其进行改进,那么您可能希望调查以下一些事项:

  • 制作一个自引用对象并将其用作 IdentityHashMap 中的键。这会不会溢出?这将是一个很好的引导,因为现在你向他们展示了这个问题的严重性:要么他们承认 java.util 中的核心类有问题,要么他们承认他们的代码有问题,或者他们采取IHM 和 System.iHC 的规范结合起来得出的结论是,任何尝试使用自引用对象作为 IHM 中的键的代码都是有缺陷的。如果他们不想接受这个错误,那可能就是他们最终的结局,所以请做好失望的准备。
  • 找到几个库并证明它们在 lucee 上不起作用。一个需要查看的地方是序列化库,它们声明它们支持自引用/克隆引用(例如包含自身的列表,或多次包含相同的 obj 引用)。
  • == 在 lucee 中的表现如何? new String("foo") == new String("foo") 是否等于 true?

但最重要的是对露西人保持一些耐心。由于他们所使用的平台的限制,他们完全有可能无法真正实现 System.iHC,在这种情况下,他们只能表示同情和耸耸肩。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。