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

int[] vs. Integer[]

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

但是我希望JVM能够在整个引擎中做一些神奇的聪明才智,因为整数是不可变的并且存储它就像一组int。

我的希望是天真的吗? 在每个最后一盎司性能都很重要的应用程序中,Integer数组是否比int数组慢得多?

===============>>#1 票数:12 已采纳

我知道没有VM会存储一个类似int []数组的Integer []数组,原因如下:

  1. 数组中可以有null的 Integer对象,并且没有剩下的位用于在int数组中指示它。 VM可以将每个阵列插槽中的这1位信息存储在hiden位阵列中。
  2. 您可以在Integer数组的元素中进行同步。 作为第一点,这很难克服,因为您必须为每个阵列插槽存储一个监视器对象。
  3. 可以比较Integer []的元素的身份。 例如,您可以通过new创建值为1的两个Integer对象,并将它们存储在不同的数组槽中,然后检索它们并通过==进行比较。 这必然会导致错误,因此您必须将此信息存储在某处。 或者你在某处保留对其中一个Integer对象的引用并使用它进行比较,你必须确保其中一个==比较是假的,一个是真的。 这意味着对于优化的 Integer数组,对象标识的整个概念很难处理。
  4. 您可以将Integer []转换为例如Object []并将其传递给期望只有Object []的方法。 这意味着处理Object []的所有代码现在也必须能够处理特殊的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数组更快且内存效率更高,并且在不久的将来这种情况不会发生太大变化。

===============>>#2 票数:3

John Rose致力于JVM中的fixnums来解决这个问题。

===============>>#3 票数:1

我认为你的希望非常天真。 具体来说,它需要处理Integer可能为null的问题,而int不能。 仅这一点就足以存储对象指针。

也就是说,实际的对象指针将是一个不可变的int实例,特别是对于一个选择的整数子集。

===============>>#4 票数:0

它不会慢得多,但因为Integer []必须接受“null”作为条目而int []不必,所以会涉及一些书记,即使Integer []得到了一个INT []。

因此,如果每一个最后一盎司的性能都很重要,那么用户int []

===============>>#5 票数:0

Integer可以为null,而int不能的原因是因为Integer是一个成熟的Java对象,包含所有开销。 因为你可以写,所以有价值

Integer foo = new Integer();
foo = null; 

有人说foo会有价值,但它还没有。

另一个区别是int执行溢出计算。 例如,

int bar = Integer.MAX_VALUE;
bar++;

会快乐地增加吧,你最终得到一个非常负数,这可能不是你想要的第一个。

foo = Integer.MAX_VALUE;
foo++;

会抱怨,我认为这会是更好的行为。

最后一点是作为Java对象的Integer带有对象的空间开销。 我认为其他人可能需要在这里加入,但我相信每个对象消耗12个字节用于开销,然后用于数据存储本身的空间。 如果您追求性能和空间,我想知道Integer是否是正确的解决方案。

  ask by izb translate from so

未解决问题?本站智能推荐:

2回复

jvm如何在jvm内存中存储对象

通过ClassLoader进行类加载的结果是,将在堆上创建Class对象(类java.lang.Class的对象)。 这是由班级计划作为其状态所组成的。 从类创建的每个对象都将链接到其Class对象(可从Object类中可用的getClass()方法获得-每个对象中都可用)。 同样由于类加
1回复

JVM如何在内部类中存储到封闭类的链接?

具有以下代码: public class Main { private Main() {} class Test extends Main { { System.out.printf("This: %h\nEnclosed in: %
5回复

JVM如何在内部处理竞争条件?

如果多个线程尝试更新相同的成员变量,则称其为竞争条件。 但是我更感兴趣的是,如果我们不通过使它同步或其他东西在我们的代码中处理它,JVM如何在内部处理它? 它会挂起我的程序吗? JVM将如何应对? 我认为JVM会暂时为这种情况创建一个同步块,但我不确定究竟会发生什么。 如果你们中的
2回复

其中基元数组存储在JVM内存中

JVM内存分为:1。方法区2.堆区3.堆栈4. PC寄存器5.本机堆栈 现在假设我有一个具有“int [] dealCodes”属性的类(int primitive的数组)。 根据内存管理,一旦交易代码被初始化,内存中将存在(total_elements * 4字节)的连续内存分配。
1回复

Java,JVM内部

我在Windows 10计算机上运行Eclipse,Tomcat,基于servlet的Web应用程序。 我想知道将创建多少个JVM实例? 同样,何时在启动或启动任何基于Java的应用程序时在Windows 10中实例化JVM。
2回复

如何在JVM中实现Java int []数组?

我试图理解JVM如何在内部实现基本类型的数组,如int [] 我的问题分为两部分: 1 - 它是否在内部使用ByteBuffer? 我在哪里可以找到源代码,然后根据我的需要进行更改(制作我自己的修改过的JVM)。 2 - 有没有办法欺骗javac不使用int []的内置实现,
2回复

JVM为什么返回此整数?

我已经做了一个非常简单的数字舍入应用程序,因为我是一个初学者,可能会有一些错误,需要进行一些调试,我们可以继续进行下去,但这不是我在这里的原因。 每当我输入大于“ int”的容量的整数时,它要么返回“ -1”,要么返回一个非常大的小数字(它是负数,因此更远离零),例如“ -572589576”
7回复

从JVM内部修改JVM args

有没有办法从jvm里面修改jvm args? 具体来说,我希望能够从内部更改jvm的最大堆大小。 这可能吗? 编辑 :我想我应该添加我想要这样做的原因。 我有一些在不同的机器/平台上运行的Java程序。 这些程序具有在运行时获取的配置,并且根据程序运行的计算机/环境而不同。 其中
1回复

Linux JVM上对象的内部锁定

我了解到:“每个对象都有与之相关的内在锁定。” 我还了解到,在Linux上,JVM内部使用POSIX api来实现多线程功能。 JVM用于为类的每个对象实例提供(创建)内部锁的POSIX API的名称是什么?
1回复

从JVM内部访问JMX

是否可以从该JVM实例内部访问JVM的JMX服务器? 还是我必须通过标准的套接字/端口远程接口进行连接? 上下文:我正在尝试实现一个“智能”系统,该系统响应JVM状态,特别是内存使用情况,在将工作数据缓存到磁盘之间进行转换,并将其保存在ram中。 设置JMX侦听器似乎比运行执行以下操