【问题标题】:Is array in java virtually sequential memory data structure? or physically sequential?java中的数组实际上是顺序内存数据结构吗?还是物理顺序?
【发布时间】:2014-07-17 09:38:15
【问题描述】:

我试图找出原始 java 'array' 和 'List' 数据结构(如 ArrayList)之间的区别,并找到类似的文章或问答(Difference between List and Array)。许多文章包括那个链接点,java原始“数组”是“顺序内存”。在这一点上,究竟什么是顺序的?这在物理内存中真的是连续的吗?还是在虚拟内存中顺序?我的猜测是虚拟内存中的顺序,因为操作系统通常分配物理内存,而应用程序(JVM)不关心特定的内存分配。但我不知道确切的答案。

【问题讨论】:

    标签: java arrays memory


    【解决方案1】:

    Java 数组在虚拟内存中是连续的,不一定在物理内存中。

    用户空间应用程序(例如 JVM)对于组成其虚拟地址空间的物理页面在内存中是否连续没有发言权。事实上,在典型的现代操作系统中,它甚至无法知道这一点。这一切都被机器的虚拟内存硬件和(用户空间)指令集架构对用户空间应用程序隐藏了。


    查看 JVM 规范不会对物理内存问题有指导意义。它根本不相关/超出范围。

    JVM 规范没有强制数组在虚拟内存中是连续的。但是,涉及非连续虚拟内存的(假设)数组实现会导致昂贵的数组操作,因此您不太可能找到这样做的主流 JVM。

    参考资料:

    • JVM Spec 2.7 说:

      “Java 虚拟机不要求对象有任何特定的内部结构。”

      规范的其他部分暗示“对象”在这里指的是类和数组的两个实例。

    • JVM Spec 2.4 谈到了数组,但没有提到它们在内存中是如何表示的。


    数组和ArrayLists的区别在更高的层次。数组具有固定大小。 ArrayLists 具有可变大小。但在底层,ArrayList 是使用(单个)数组实现的……如果列表变得太大,可以重新分配(即替换)。

    【讨论】:

    • 感谢您的回答。总之,当系统访问内存时,顺序是物理顺序内存>虚拟顺序内存>其他。对吗?
    • 我不明白你在问什么。
    • 访问时间的问题。我认为访问物理顺序项所需的时间比虚拟顺序项要快。
    • 不一定。问题是您绝对不能关闭虚拟内存支持。因此,即使内存页在物理上是连续的,当您跨页边界寻址时,您仍然会面临相同的(潜在)页表查找开销。
    【解决方案2】:

    您必须查看 JVM 规范以查看是否有任何此类要求(数组是否需要是顺序内存),但出于效率目的,以 malloc 类型的方式分配数组是有意义的.

    对于虚拟与物理,一切(操作系统之上)都使用虚拟内存。 JVM 的级别不够低,无法访问内核在 Ring-0 上所做的事情。

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

    【讨论】:

    • 感谢您的回答。你提到了malloc,但是vmalloc和kmalloc是不同的……你的意思是vmalloc?
    • 是的,vmalloc。 JVM 访问物理内存是完全没有必要的(更不用说危险了)。
    【解决方案3】:

    JVM 从操作系统获取虚拟顺序内存。只有在操作系统级别,才能按顺序分配物理内存。

    同样重要的是不要混淆顺序内存分配和顺序访问 - 顺序访问 意味着以预定的有序顺序访问一组元素。如果一个数据结构只能以一种特定的顺序访问它包含的值,则称该数据结构具有顺序访问。典型的例子是链表。 而顺序内存意味着分配顺序内存(不一定是物理顺序的,但实际上是顺序的)。

    除了您发布的链接之外,ArrayArrayList 之间的一些主要区别是:

    • 数组大小固定,ArrayList 大小动态
    • Array可以存储原语,ArrayList只能存储Objects(Wrapper 基元类型)
    • 您可以在 ArrayList 中使用泛型
    • 您可以使用 add() 方法将元素插入到 ArrayList 中,您可以 只需使用赋值运算符将元素存储到数组中

    参考:Java67 articleWikipedia

    【讨论】:

    • 是的,谢谢你的回答。我只是想知道java中的数组是如何在物理内存中表示的。
    【解决方案4】:

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

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

    总结一下:

    class A {
    int x;
    int y;
    }
    
    
    
    public void m1() {
    int i = 0;
    m2();
    }
    
    public void m2() {
    A a = new A();
    }
    

    当m1被调用时,一个新的帧(Frame-1)被压入堆栈,并且在Frame-1中也创建了局部变量i。 然后在 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 添加了概要
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    • 2017-06-11
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多