簡體   English   中英

Java/ColdFusion 和 Lucee 之間的 identityHashCode 區別

[英]identityHashCode difference between Java/ColdFusion and Lucee

編輯:錯誤已提交。

假設我有兩個相互指向的 ArrayList(循環引用):

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

如果我在其中任何一個上調用hashCode ,則會由於 ArrayList implementation導致StackOverflowError 這是可以預料的。

但是,當我調用System.identityHashCode時,它不應該使用Object.hashCode實現,它不會遵循 ArrayList 中的元素,因此不會導致StackOverflowError

identityHashCode的文檔說明:

為給定的 object 返回與默認方法 hashCode() 返回的相同的 hash 代碼,無論給定對象的 class 是否覆蓋 hashCode()。

在 Adobe ColdFusion 中,此代碼工作正常:

System = createObject("java", "java.lang.System");

System.identityHashCode(x); // returns some integer
System.identityHashCode(y); // returns another integer

(這顯然也適用於本機編譯並使用 Java 運行時。)

然而,在 Lucee 中,它會立即導致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)
    [...]

為什么它在這里運行hashCode的 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 即使在(最終)引用自身的 object 中也不會永遠循環的人。

但是,關鍵是,這些是廣泛使用的假設 該方法的規范中沒有任何內容實際上說明它以這種方式工作。

另一方面,lucee 所采取的回旋余地(如果您所說的確實是真的)相當過分。

因此,您現在陷入困境。 這些都是真的:

  • 大量代碼假定 iHC 無法循環。 因此,事實上,VM impl 會循環是非常不切實際的。
  • 大量代碼假設 iHC 速度很快。 因此,事實上,VM impl 會很慢是非常不切實際的。
  • 盡管如此,Lucee 可以 go '我是橡膠,你是膠水,無論你的錯誤報告從我身上反彈並堅持你'的路線,只是告訴你他們的 impl 根據規范是有效的,因此無論你關心什么代碼向他們折騰以表明您的觀點是錯誤的。

但是先給他們一個機會,在你認為他們會打開門之前'nu uh。 不是我們的錯! 技術上可供他們使用的路線。

如果他們拒絕了您的錯誤報告,並且/或者您想在將其提交到他們的錯誤跟蹤器之前對其進行一些改進,那么您可能希望調查以下一些事情:

  • 制作一個自引用的 object 並將其用作 IdentityHashMap 中的鍵。 這個stackoverflow嗎? 這將是一個很好的領導,因為現在你向他們展示了這個問題的嚴重性:要么他們承認 java.util 中的核心 class 是錯誤的,要么他們承認他們的代碼有錯誤,或者他們采取更奇特的 position 將 IHM 和 System.iHC 的規范結合起來得出結論,任何試圖在 IHM 中使用自引用對象作為鍵的代碼都是錯誤的。 如果他們不想接受這個錯誤,那可能就是他們最終的結果,所以要做好失望的准備。
  • 找到幾個庫並證明它們不能在 lucee 上工作。 一個值得一看的地方是 state 的序列化庫,它們支持自引用/克隆的引用(例如包含自身的列表,或多次包含相同的 obj 引用)。
  • ==在 lucee 中表現如何? new String("foo") == new String("foo")是否等於 true?

但最重要的是對 lucee 人保持一定的耐心。 由於他們正在使用的平台的限制,他們完全有可能沒有真正的方法可以實際實現 System.iHC,在這種情況下,他們無能為力,只能同情和聳聳肩。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM