Java:1-d数组在内存中是否总是连续的?

shr*_*000 25 java arrays

我读过很多关于这个主题的书籍和文章,以及我用'Unsafe'编写的一个小程序,表明Java中的1-d数组在内存中总是连续的.它是由JLS规定还是实施惯例?要求提出这个问题.

Mat*_*arz 19

不,JVM规范没有任何此类保证:http: //docs.oracle.com/javase/specs/jvms/se5.0/html/Concepts.doc.html#16446

在实践中可能是这种情况,但您也无法保证字数.

不安全不是标准的Java类,所以如果你的程序使用它,那么它无论如何都不可移植......


lik*_*ern 12

我想用Java语言规范,Java SE 8 Edition(JLS)Java虚拟机规范,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.对象.

对象是类实例或数组.(和Array是Object)

同时JVMS说对象和数组存储在堆上:

2.5.3.堆

Java虚拟机具有在所有Java虚拟机线程之间共享的堆.堆是运行时数据区,从中分配所有类实例和数组的内存.

但是JVMS并不强制堆内存是连续的:

2.5.3.堆

... 堆的内存不需要是连续的.

由于所有数组都存储在堆中,并且堆可能不连续,因此数组也可能不连续.

  • 整个堆不连续并不能得出任何特定对象可能不连续的结论。这可能是一个事实,但它并不是从这个前提得出的,也不是从数组是对象的事实得出的。 (5认同)

Joa*_*uer 10

由于没有真正的方法与Java中的内存地址进行交互,因此在规范中也没有定义内存中对象的布局如何.

请注意,使用Unsafe非常自动意味着您在规范领域之外漫步.

话虽如此,我敢说大多数JVM实现确实使用(一维)数组的线性布局.


Pet*_*rey 7

鉴于许多 JVM 要求堆在内存中是连续的,我认为他们不太可能在内存中的不同位置放置一维原语数组。

Object[] 引用的对象不太可能在内存中是连续的,即使它们是连续的,也可以在没有警告的情况下重新排列。

注意:使用 Unsafe,您可以将数组中的引用作为int值读取,以查看它们在 GC 之前和之后的内容。一些 JVM 使用需要很长的 64 位引用,但大多数使用 32-bti 引用(即使对于 64 位 JVM)

  • @shrini1000 如果堆不是连续的虚拟内存块,那么跨越两个片段的数组将不会有连续的布局。另一方面,连续的堆并不意味着数组也是如此,也许只是间接地使它更有可能,因为 GC 设计约束将是相似的。 (3认同)
  • @MarkoTopolnik 另外我的想法是,如果他们没有看到需要分解堆(这在 32 位 Windows 上很痛苦),我不明白他们为什么要为单个数组这样做。 (3认同)
  • 同意,但数组本身将是连续的,对吗?像这样:1000->aa、1001->bb、1002->cd 等等。 (2认同)