2012-04-19 445 views
21

我在這個主題上閱讀過的很多書籍和文章,以及我用'不安全'寫的一個小程序,都表明Java中的一維數組在內存中始終是連續的。那麼它是由JLS規定還是實施慣例?這個問題被要求確認這個指示。Java:一維數組是否總是在內存中連續?

回答

10

由於在Java中沒有真正的與內存地址交互的方式,所以在規範中也沒有定義內存中對象佈局的外觀。

請注意,使用Unsafe幾乎會自動意味着您正在漫遊規範領域之外。這就是說,我敢說大多數JVM實現實際上使用線性佈局(一維)數組。

3

鑑於許多JVM的有一個要求,即堆是連續在內存中,我認爲它不太可能他們會在內存中的不同位置放置一個1d的基元數組。

Object []引用的對象不可能在內存中連續存在,即使它們是可以在沒有警告的情況下重新排列。

注意:使用不安全,您可以讀取數組中的引用作爲int值,以查看GC之前和之後的內容。某些JVM使用64位引用,這需要很長的時間,但大多數情況下使用32位bti引用(即使是64位JVM)。

+2

同意,但陣列本身將是連續的,對不對?這樣的事情:1000-> aa,1001-> bb,1002-> cd等 – shrini1000 2012-04-19 09:17:22

+1

我期望引用應該連續存儲(但我不相信它在任何地方指定)這是類似的事實,即Spec沒有說引用計數不會在任何JVM中用於GC,但是AFAIK沒有。 – 2012-04-19 09:18:35

+3

@ shrini1000如果堆不是連續的虛擬內存塊,則數組跨越兩個片段將不會有連續的佈局。另一方面,堆是連續的並不意味着數組也是這樣,也許只是間接地使它更有可能,因爲GC設計約束是相似的。 – 2012-04-19 09:27:50

8

我想用The Java Language Specification, Java SE 8 Edition (JLS)The Java Virtual Machine Specification, Java SE 8 Edition (JVMS)對此的看法來刷新此問題。

我們必須的選擇,這個問題的答案:

  1. 在JVM實現強加什麼約束。這是最可靠的方法,因爲任何規範的實現固有地假定爲「允許的所有不被禁止的」原理。
  2. 最令JVM實現合理的建議

我會指出來規範約束。

如果我們看一下第10章陣列的 JLS(以及相關的陣列JLSJVMS任何其他章節),我們找不到強加給數組的內存佈局約束任何提及。 因此,它肯定意味着該陣列可能不是連續的

此外,JLS說,陣列是對象

第10章陣列。

在Java編程語言中,數組是 對象(第4.3.1節),被動態地創建,並且可以被分配給Object類型的 變量(§4.3.2)。類Object中的所有方法可能是在數組上調用 。
...

4.3.1。對象。

一個目的是類實例或陣列。 (和陣列是Object)

並在同一時間JVMS說,對象和數組存儲在堆上:

2.5.3。堆

Java虛擬機具有在所有Java虛擬機線程中共享的堆。 堆是運行時數據區域 ,從中分配所有類實例和數組的內存。

JVMS不會強迫堆內存是連續的:

2.5.3。堆

... 堆的內存不需要連續。

由於所有數組存儲在堆和堆可能是不連續的,它遵循陣列也可能是不連續的。

+0

只是一個註釋:[什麼時候應該使用代碼格式來處理非代碼文本?](http://meta.stackoverflow.com/a/254995):)。 – Tom 2015-07-25 08:59:41

+0

我會如何處理官方規範中的類似引文?我希望將它們與其他文字分開以便更好地閱讀。 – likern 2015-07-25 09:09:10

+0

請注意「代碼格式」和「blockquote」之間的區別。諸如「JLS」,「JVMS」和「Chapter 10. Arrays」等詞。沒有代碼,應該格式化爲:)。引號是正確的。 – Tom 2015-07-25 09:21:23

相關問題