Java对象数组是如何使用的?
我们正在尝试调整一些Oracle JVM垃圾收集选项,一位开发人员试图使用Java对象数组是如何使用的?,java,c,arrays,object,garbage-collection,Java,C,Arrays,Object,Garbage Collection,我们正在尝试调整一些Oracle JVM垃圾收集选项,一位开发人员试图使用-XX:preforureSizeThreshold来确保一个大数组的对象立即被放入到了永久保存状态。我很确定这个假设是数组大小等于或超过其中所有对象的总大小 但是在Java中,对象数组不就是引用数组吗?也就是说,数组中的每个对象以及数组对象本身在内存中是独立的,并被垃圾收集器视为独立的?我认为,如果有数百万个条目,数组对象仍然可以变得相当大,但如果每个对象都比引用大得多,它不应该接近它“包含”的对象的总大小 我觉得有点混
-XX:preforureSizeThreshold
来确保一个大数组的对象立即被放入到了永久保存状态。我很确定这个假设是数组大小等于或超过其中所有对象的总大小
但是在Java中,对象数组不就是引用数组吗?也就是说,数组中的每个对象以及数组对象本身在内存中是独立的,并被垃圾收集器视为独立的?我认为,如果有数百万个条目,数组对象仍然可以变得相当大,但如果每个对象都比引用大得多,它不应该接近它“包含”的对象的总大小
我觉得有点混乱,因为在C中:
struct
s数组来真正存储struct
sstruct
s的指针数组ArrayList
与频繁的append()
s一起使用(就像我们手头的情况一样),该怎么办?是否仅复制阵列,而不复制阵列中的对象?另外,当复制数组时,即使旧数组是终身的,新数组也会从伊甸园开始,对吗
但是在Java中,对象数组不就是引用数组吗
只是参考资料。所有对象都是在堆上分配的,而不是在数组或堆栈上分配的(至少在官方情况下,优化器可能会使用堆栈分配,但这是透明的)
如果每个对象都比一个引用大得多,那么它不应该接近它“包含”的对象的总大小
是的,在Java中,每当你说“分配/存储一个对象”时,你指的是引用(C术语中的指针)
如果我使用带有频繁append()s的ArrayList(就像我们手头的例子一样),会怎么样?是否仅复制阵列,而不复制阵列中的对象
阵列仅在需要调整大小时才被复制,即很少复制,且摊销成本与插入数成比例。引用的对象永远不会被复制
另外,当复制数组时,即使旧数组是终身的,新数组也会从伊甸园开始,对吗
对!
但是在Java中,对象数组不就是引用数组吗?即。
数组中的每个对象以及数组对象本身都是
在内存中分离并被垃圾收集器视为分离
对
我觉得有点混乱,因为在C中:
int[]
数组通常会为数组保留10×4字节,再加上整个数组对象的开销
然而,正如您所说,对象数组是引用数组。因此,一个包含10个元素的对象[]
通常会占用数组的10×4字节(或者在64位CPU上可能是10×8字节),加上开销,再加上每个非空元素引用的每个对象的空间。这在C中对应于指针数组
(我使用术语“通常”,因为即使大多数JVM都是这样做的,它们也不需要以任何特定的方式分配内存。)
还要注意,Java没有像C(或C#)那样的真正的多维数组。Java中的int[]]
实际上是一个一维数组,其中每个元素都是对自己的int[]
子数组的引用。在C语言中,int[][]
实际上是一个二维整数数组(在编译时必须知道除第一个维度以外的所有维度的长度)
附录
还要注意,正如您所说,C可以有真正的结构数组,这些结构既不是基元类型,也不是指针。Java没有此功能。使用
-XX:precuresizethreshold
进行调优不太可能对您有所帮助。
此参数仅适用于直接Eden分配,而大多数分配发生在TLAB(线程本地分配缓冲区)中,并且忽略-XX:precuresizethreshold
对于线程主动分配内存(数兆字节),TLAB可能相当大
您可以调整TLAB大小,以减少这种影响,但这可能弊大于利。您基本上是正确的。在Java中,非原语数组始终是引用数组。如果重新分配了ArrayList,则新数组将开始“刷新”。(这并不是说有些JVM不会对某些场景进行特殊处理,但这几乎是一次性的,并且针对特定的(即,基准测试关键)情况。)您是想引用同样的内容两次吗?不过,你回答了所有的问题,所以我接受了:)哇。这听起来很糟糕,但也许Java的分配足够好,可以最大限度地保持数据的邻接性。如果不是。。嗯,这是性能损失的悲剧。@Thumbz:当然,分配器会将分配的对象放在相邻的行中(除非它自己必须获得新的内存块)。但是接下来的是。。。它也试图保留地方性,但它变得更加复杂。有时这可能是一个问题,但不要忘记。通常我同意过早优化的概念,但当涉及到日常结构和数据的邻接性时。。嗯,从磁盘读取是很慢的。这是大多数编程的瓶颈。。基本上,任何在合成中不是很重的东西。。。(我毫不犹豫地说