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)来解释这个问题。
我们必须选择回答这个问题:
- 对JVM实现施加了哪些约束 。 这是最可靠的方法,因为任何规范的实现都固有地假定“允许一切不被禁止”的原则。
- 大多数JVM实现建议合理
我将指出规范约束。
如果我们看一下第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。 堆
… 堆的内存不需要是连续的。
由于所有数组都存储在堆中,并且堆可能不连续,因此数组也可能不连续。
鉴于许多JVM都要求堆在内存中连续存在,我认为它们不太可能将1d基元数组放在内存中的不同位置。
Object []引用的对象不太可能在内存中连续,即使它们是,也可以在没有警告的情况下重新安排。
注意:使用Unsafe,您可以将数组中的引用读取为int
值,以查看GC之前和之后的内容。 一些JVM使用64位引用,这些引用需要很长但大多数使用32-bti引用(即使对于64位JVM)
- java.lang.NoClassDefFoundError:org / hibernate / cfg / Configuration
- 如何在运行时调整log4j级别?
- 将文件类型与Java Swing应用程序关联
- inheritanceJava集合接口(Set,Map,List等)的C ++等价物是什么? 或者扩展AbstractCollection?
- Java中的InputStream的多个读者
- 选择哪个Eclipse IDE版本?
- 限制嵌入式Groovy中的某些API
- 查询方法public abstract java.util.List的validation失败
- Hibernate – 从多个表到一个对象的复杂查询