当前位置: 首页 > 面试题库 >

Integer数组如何在JVM内部存储?

秦联
2023-03-14
问题内容

java中的一个int数组作为一个32位值块存储在内存中。如何存储整数对象数组?即

int[] vs. Integer[]

我以为Integer数组中的每个元素都是对Integer对象的引用,并且Integer对象与其他任何对象一样都具有对象存储开销。

但是,我希望JVM能够在底层实现一些神奇的功能,因为Integer是不可变的,并且像整数数组一样存储它。

我的希望真是天真吗?在性能至关重要的应用程序中,整数数组是否比整数数组要慢得多?


问题答案:

我所知的任何VM都不会像int []数组那样存储Integer []数组,原因如下:

  1. 数组中可以 有空的 Integer对象,并且在int数组中没有剩余的用于指示此对象的位。但是,VM可以将每个阵列插槽的1位信息存储在隐藏位数组中。
  2. 您可以在Integer数组的元素中进行同步。首先,这很难克服,因为您必须为每个阵列插槽存储一个监视对象。
  3. 可以比较Integer []的元素的身份。例如,您可以通过 new 创建两个值为1的Integer对象,并将它们存储在不同的数组插槽中,然后检索它们并通过==比较它们。这必须导致错误,因此您必须将此信息存储在某处。或者,您在某处保留对一个Integer对象的引用,并使用该引用进行比较,并且必须确保==比较之一为false,而另一为true。这意味着对于 优化的 Integer数组,对象标识的整个概念很难处理。
  4. 您可以将Integer []强制转换为例如Object [],并将其传递给仅需要Object []的方法。这意味着所有处理Object []的代码现在也必须能够处理特殊的Integer []对象,从而使其变慢和变大。

考虑到所有这些因素,可能有可能制作一个特殊的Integer [],相比于 朴素的
实现,它可以节省一些空间,但是额外的复杂性可能会影响很多其他代码,最终使它变慢。

使用Integer []代替int
[]的开销在空间和时间上可能非常安静。在典型的32位VM上,一个Integer对象将消耗16字节(对象头为8字节,有效负载为4字节,对齐时为4个其他字节),而Integer
[]则使用与int
[]一样多的空间。在64位VM(使用64位指针,并非总是如此)中,一个Integer对象将消耗24个字节(标头为16个字节,有效负载为4个字节,对齐方式为4个字节)。另外,Integer
[]中的插槽将使用8个字节,而不是int []中的4个字节。这意味着您可以预期每个插槽的开销为 16到28 个字节,与普通int数组相比,这是
4到7倍

性能开销也可能很重要,主要有两个原因:

  1. 由于使用了更多的内存,因此给内存子系统带来了更大的压力,在Integer []的情况下,它更有可能发生高速缓存未命中。例如,如果您以线性方式遍历int []的内容,则高速缓存将在需要时已提取大多数条目(因为布局也是线性的)。但是在使用Integer数组的情况下,Integer对象本身可能会随机分散在堆中,这使缓存很难猜测下一个内存引用将指向的位置。
  2. 由于使用了额外的内存,垃圾收集必须做更多的工作,并且必须分别扫描和移动每个Integer对象,而对于int []来说,它只是一个对象,而对象的内容不必须进行扫描(它们不包含对其他对象的引用)。

综上所述,在当前性能要求较高的工作中使用int []会比在当前VM中使用Integer阵列更快,内存效率更高,而且在不久的将来这种变化不太可能发生。



 类似资料:
  • 直到今天,我才知道java有堆,堆是由JVM创建的。此外,这个内存是由操作系统分配给JVM实例的,即堆驻留在JVM实例中。 这表明,JVM和堆相距甚远。 所以,我现在很困惑,有谁能让我知道,我以前是错的还是我不能理解这幅画?

  • JVM内存分为:1.方法区2.堆区3.堆栈4.PC寄存器5.本机堆栈 > 现在假设我有一个属性为“int[]dealCodes”(int基元数组)的类。根据内存管理,一旦处理代码初始化,内存中就会有连续内存分配(total_elements*4字节)。所以,如果数组大小为10,则JVM内存中有40字节的分配。 我的问题是,这40个字节将分配到哪个区域(堆还是堆栈)? 我对数组的理解是:它就像任何其

  • 我想改变(增加)Java内存限制(Windows PC上的JRE)。我到处都遵循以下命令: -xms设置初始Java堆大小 -Xmx设置最大Java堆大小 例如-Xmx1024m。 但我的问题是在哪里!我必须输入这个命令吗?抱歉这个初学者的问题。通常我对java没有任何接触。

  • 除了这些地方之外,hostspot JVM进程还在哪里存储内存: 烫发 终身制发电 伊甸园空间 从空间 到空间 代码缓存 也就是说:热点进程可以保留哪些可能的方式 我能想到的一些答案(让我知道这些是不是真的): 用于线程栈的虚拟内存没有用这些数字表示 任何加载的dll或文件。 编辑: 给出的一些其他答案: Java.exe本身 JNI方法可以分配内存本身 任何本机代码(例如来自DLL)都可以分配内

  • 问题内容: 我想知道Swift如何在内部管理数组?Apple的语言指南仅处理用法,而未详细说明内部结构。 作为一名Java开发人员,我习惯于将“裸”数组视为一种非常静态和固定的数据结构。我知道这在Swift中是不正确的。除了Java之外,在Swift中,您可以更改数组的长度,还可以执行插入和删除操作。在Java中,我习惯于根据要对该结构执行的操作来决定要使用哪种数据结构(简单数组,ArrayLis

  • 问题内容: 嗨,我想知道我可以根据我的应用程序增加JVM的内存。如果是,如何增加JVM的内存?我怎么知道JVM的大小? 问题答案: 启动JVM时,可以调整两个参数以适合你的内存需求: 指定初始Java堆大小,并 最大Java堆大小。 http://www.rgagnon.com/javadetails/java-0131.html