为什么在Java中分配对象/数组时会产生开销?


9

Java中数组占用多少字节?假设这是一台64位计算机,并且还假设一个数组中有N个元素,那么对于不同类型的数组,所有这些元素将占用2 * N,4 * N或8 * N个字节。

在Coursera的一次演讲中说,对于一个N元素数组,它将占用2 * N + 24、4 * N + 24或8 * N + 24个字节,而这24个字节称为开销,但没有说明为什么开销是需要。

对象也有开销,为16个字节。

这些间接费用到底是什么?这些24/16字节由什么组成?

另外,这些开销仅存在于Java中吗?C,C ++和Python呢?



1
@Gnijuohz:您的意思是问:开销由什么数据组成?
FrustratedWithFormsDesigner 2012年

@YannisRizos:我认为OP想要知道数组中这24个字节中的实际值。
FrustratedWithFormsDesigner 2012年

@FrustratedWithFormsDesigner啊,这似乎比我的问题更好地解释了问题。
扬尼斯,2012年

@YannisRizos对我的不良态度感到抱歉。但是,当您发布该链接时,我不禁会认为这是一种讽刺。我猜是太防御了。
Gnijuohz 2012年

Answers:


16

每个Java对象都有一个标头,其中包含对JVM重要的信息。最重要的是对对象类的引用(一个机器字),垃圾回收器使用一些标志来管理同步(因为每个对象都可以同步),这占用了另一个机器字(使用部分字会对性能不利)。这就是2个字,在32位系统上为8个字节,在64位系统上为16个字节。数组还需要一个int字段来表示数组长度,这是另外4个字节,在64位系统上可能是8个字节。

至于其他语言:

  • C没有对象,因此它当然没有对象标头-但是在每个单独分配的内存上可能都有标头。

  • 在C ++中,您没有垃圾回收,也不能使用任意对象进行同步,但是,如果您的类具有重写的方法,则每个对象都有一个指向其vtable的指针,就像Java对象对其类的引用一样。如果使用进行垃圾收集的智能指针,则它们需要内部管理数据。

  • 我不了解Python,但是我很确定它还需要引用该类以及垃圾收集器的内部维护信息。


目前,OpenJDK中正在开展工作以减少对象标头的大小,这是很小但很重要的步骤:-)
Martijn Verburg,2012年

在C ++中,只有多态类需要vtable。std::pair<int, float>是一个简单的类,根本不需要vtable。结果,它可能非常适合8个字节。此外,智能指针实际上不需要添加内务处理。一个明显的反例是std::unique_ptr<T>,它通常与原始大小一样T*(unique_ptr当然不执行GC)。
MSalters

4
C也有开销,每个malloc分配的内存块都需要一个标头,free然后使用该标头。
herby 2012年

据我所知,至少有一个malloc库在32位系统上使用8字节的标头(4字节的长度由两组2字节的前哨值IIRC括起来)。
Donal Fellows
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.