我读过很多关于这个主题的书籍和文章,以及我用'Unsafe'编写的一个小程序,表明Java中的1-d数组在内存中总是连续的。它是由JLS规定还是实施惯例?要求提出这个问题的确认。
答案 0 :(得分:19)
不,JVM规范没有任何此类保证: http://docs.oracle.com/javase/specs/jvms/se5.0/html/Concepts.doc.html#16446
在实践中可能就是这种情况,但您也无法保证字数。
Unsafe不是标准的Java类,所以如果你的程序使用它,那么它无论如何都不可移植......
答案 1 :(得分:10)
由于没有真正的方法与Java中的内存地址进行交互,因此在规范中也没有定义内存中对象的布局如何。
请注意,自动使用Unsafe
意味着您在规范范围之外漫步。
话虽如此,我敢说大多数JVM实现做实际上使用线性布局(一维)数组。
答案 2 :(得分:10)
我想用The Java Language Specification, Java SE 8 Edition (JLS)和The Java Virtual Machine Specification, Java SE 8 Edition (JVMS)所说的内容来刷新这个问题。
我们必须选择回答这个问题:
我将指出规范约束。
如果我们查看 JLS 的第10章数组(以及 JLS 和 JVMS 的任何其他章节)与数组相关)我们找不到任何关于对数组施加的内存布局约束的提及。 因此,它绝对意味着数组可能不连续。
此外, JLS 表示数组是 Objects :
第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。堆
... 堆的内存不需要是连续的。
由于所有数组都存储在堆中,而堆可能不连续,因此数组也可能不连续。
答案 3 :(得分:4)
鉴于许多JVM都要求堆在内存中连续存在,我认为不太可能将1d基元数组放在内存中的不同位置。
Object []引用的对象不太可能在内存中连续存在,即使它们存在,也可以在没有警告的情况下重新安排。
注意:使用Unsafe,您可以将数组中的引用读取为int
值,以查看GC之前和之后的内容。一些JVM使用64位引用,这些引用需要很长但大多数使用32-bti引用(即使对于64位JVM)