[英]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
?
為給定的 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 所采取的回旋余地(如果您所說的確實是真的)相當過分。
因此,您現在陷入困境。 這些都是真的:
但是先給他們一個機會,在你認為他們會打開門之前'nu uh。 不是我們的錯! 技術上可供他們使用的路線。
如果他們拒絕了您的錯誤報告,並且/或者您想在將其提交到他們的錯誤跟蹤器之前對其進行一些改進,那么您可能希望調查以下一些事情:
==
在 lucee 中表現如何? new String("foo") == new String("foo")
是否等於 true?但最重要的是對 lucee 人保持一定的耐心。 由於他們正在使用的平台的限制,他們完全有可能沒有真正的方法可以實際實現 System.iHC,在這種情況下,他們無能為力,只能同情和聳聳肩。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.