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

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

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

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

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

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

请注意,几乎自动使用Unsafe意味着您在规范范围之外漫步。

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

我想用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。 堆

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

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

鉴于许多JVM都要求堆在内存中连续存在,我认为它们不太可能将1d基元数组放在内存中的不同位置。

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

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