Java中的数组是虚拟的顺序内存数据结构还是物理上的顺序内存数据结构?

3

我试图找出Java原始“数组”和“List”数据结构(如ArrayList)之间的区别,并找到了像这样的文章或Q&A(Difference between List and Array)。许多文章,包括该链接,指出Java原始“数组”是“顺序内存”。在这一点上,“顺序”究竟是什么意思?这真的是物理内存中的顺序吗?还是虚拟内存中的顺序?我的猜测是虚拟内存中的顺序,因为操作系统通常分配物理内存,应用程序(JVM)不关心具体的内存分配。但我不知道确切的答案。

4个回答

4
Java数组在虚拟内存中是连续的,但不一定在物理内存中也是连续的。
用户空间应用程序(如JVM)无法决定其虚拟地址空间所占据的物理页面是否在内存中是连续的。实际上,在典型的现代操作系统中,用户空间应用程序甚至无法知道这一点。机器的虚拟内存硬件和(用户空间的)指令集架构都将这一切隐藏起来。
查阅JVM规范对于物理内存问题没有指导意义。它根本不相关/超出范围。JVM规范不强制要求数组在虚拟内存中是连续的。然而,涉及非连续虚拟内存的(假设的)数组实现会导致昂贵的数组操作,因此你不太可能找到一个主流的JVM做这个。参考资料: JVM规范2.7表示:“Java虚拟机不强制要求对象有特定的内部结构。” 规范的其他部分暗示“对象”在这里指类的实例和数组两者都包含。JVM规范2.4讨论了数组,但未提及它们如何在内存中表示。
数组和 ArrayList 的区别在于更高的层面上。数组具有固定大小,而 ArrayList 具有可变大小。但在底层,一个 ArrayList 是使用一个(单一)数组实现的...如果列表增长得太大,该数组可以被重新分配(即替换)。

感谢您的回答。总之,当系统访问内存时,顺序是物理连续内存>虚拟连续内存>其他。对吗? - Stephen Choi
我不明白你在问什么。 - Stephen C
这是关于访问时间的问题。我认为,访问物理上连续的项目所需的时间比访问虚拟上连续的项目要快。 - Stephen Choi
不一定。问题在于你通常无法关闭虚拟内存支持。因此,即使内存页在物理上是连续的,当你跨越页面边界寻址时仍然存在相同(潜在的)页表查找开销。 - Stephen C

2

要确定是否需要将数组分配到连续内存中,您需要查看JVM规范,但出于效率考虑,以malloc类型的方式分配数组是有意义的。

至于虚拟内存与物理内存,所有(操作系统以上的)都使用虚拟内存。 JVM不够低级别,无法访问Ring-0层次的内核资源。

最后,您为什么感兴趣? 您在编写自己的JVM吗?


谢谢回答。您提到了 malloc,但 vmalloc 和 kmalloc 是不同的...您是指 vmalloc 吗? - Stephen Choi
是的,vmalloc。让JVM可以访问物理内存是非常不必要的(更不用说危险了)。 - Kayaman

1
JVM从操作系统获取虚拟顺序内存。只有在操作系统级别上才能分配物理内存的连续区域。
同时,重要的是不要混淆顺序内存分配和顺序访问——顺序访问是指以预定的有序方式访问一组元素。如果数据结构中的值只能按照一种特定顺序访问,则称其具有顺序访问。链表是一个典型的例子。 而顺序内存意味着分配顺序内存(不一定是物理上连续的,但是在虚拟上是连续的)。
除了您发布的链接外,ArrayArrayList之间的一些主要区别包括:
  • 数组大小固定,ArrayList大小可动态增加
  • 数组可以存储原始类型,ArrayList只能存储对象(基本类型的包装类型)
  • 您可以使用泛型来处理ArrayList
  • 您可以使用add()方法将元素插入ArrayList中,也可以仅使用赋值运算符将元素存储到数组中

参考资料:Java67文章, 维基百科


1
谢谢你的回答。我只是想知道Java中的数组在物理内存中是如何表示的。 - Stephen Choi

0

这可能是一篇有趣的文章,可以解释您的问题。

  • 在Java中,数组也是对象,因此内存中对象的外观也适用于数组。

总结:

class A {
int x;
int y;
}



public void m1() {
int i = 0;
m2();
}

public void m2() {
A a = new A();
}

当调用m1时,一个新的帧(Frame-1)被推入堆栈中,局部变量i也在Frame-1中创建。 然后在m1内部调用m2,另一个新的帧(Frame-2)被推入堆栈中。在m2中,类A的对象被创建在堆中,并且引用变量被放置在Frame-2中。
物理内存位置不受您控制,将由操作系统分配。

http://www.programcreek.com/2013/04/what-does-a-java-array-look-like-in-memory/


@Andrew Stubbs添加了一个简介。 - Arno_Geismar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接