我读过很多关于这个主题的书籍和文章,以及我用'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)来解释这个问题.
我们必须选择回答这个问题:
我将指出规范约束.
如果我们看一下第10章阵列的JLS(以及任何其他章节JLS和JVMS相关阵列)我们找不到强加给数组的内存布局约束任何提及.因此,它肯定意味着数组可能不连续.
而且,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.堆
... 堆的内存不需要是连续的.
由于所有数组都存储在堆中,并且堆可能不连续,因此数组也可能不连续.
Joa*_*uer 10
由于没有真正的方法与Java中的内存地址进行交互,因此在规范中也没有定义内存中对象的布局如何.
请注意,使用Unsafe非常自动意味着您在规范领域之外漫步.
话虽如此,我敢说大多数JVM实现确实使用(一维)数组的线性布局.
鉴于许多 JVM 要求堆在内存中是连续的,我认为他们不太可能在内存中的不同位置放置一维原语数组。
Object[] 引用的对象不太可能在内存中是连续的,即使它们是连续的,也可以在没有警告的情况下重新排列。
注意:使用 Unsafe,您可以将数组中的引用作为int值读取,以查看它们在 GC 之前和之后的内容。一些 JVM 使用需要很长的 64 位引用,但大多数使用 32-bti 引用(即使对于 64 位 JVM)