Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java对象数组是如何使用的?_Java_C_Arrays_Object_Garbage Collection - Fatal编程技术网

Java对象数组是如何使用的?

Java对象数组是如何使用的?,java,c,arrays,object,garbage-collection,Java,C,Arrays,Object,Garbage Collection,我们正在尝试调整一些Oracle JVM垃圾收集选项,一位开发人员试图使用-XX:preforureSizeThreshold来确保一个大数组的对象立即被放入到了永久保存状态。我很确定这个假设是数组大小等于或超过其中所有对象的总大小 但是在Java中,对象数组不就是引用数组吗?也就是说,数组中的每个对象以及数组对象本身在内存中是独立的,并被垃圾收集器视为独立的?我认为,如果有数百万个条目,数组对象仍然可以变得相当大,但如果每个对象都比引用大得多,它不应该接近它“包含”的对象的总大小 我觉得有点混

我们正在尝试调整一些Oracle JVM垃圾收集选项,一位开发人员试图使用
-XX:preforureSizeThreshold
来确保一个大数组的对象立即被放入到了永久保存状态。我很确定这个假设是数组大小等于或超过其中所有对象的总大小

但是在Java中,对象数组不就是引用数组吗?也就是说,数组中的每个对象以及数组对象本身在内存中是独立的,并被垃圾收集器视为独立的?我认为,如果有数百万个条目,数组对象仍然可以变得相当大,但如果每个对象都比引用大得多,它不应该接近它“包含”的对象的总大小

我觉得有点混乱,因为在C中:

  • 可以有一个
    struct
    s数组来真正存储
    struct
    s
  • 也可以有一个指向
    struct
    s的指针数组
  • 我很确定Java总是使用1。对于基元类型的数组,始终使用2。对于对象数组,而C可以用于任何类型

    如果我将
    ArrayList
    与频繁的
    append()
    s一起使用(就像我们手头的情况一样),该怎么办?是否仅复制阵列,而不复制阵列中的对象?另外,当复制数组时,即使旧数组是终身的,新数组也会从伊甸园开始,对吗

    但是在Java中,对象数组不就是引用数组吗

    只是参考资料。所有对象都是在堆上分配的,而不是在数组或堆栈上分配的(至少在官方情况下,优化器可能会使用堆栈分配,但这是透明的)

    如果每个对象都比一个引用大得多,那么它不应该接近它“包含”的对象的总大小

    是的,在Java中,每当你说“分配/存储一个对象”时,你指的是引用(C术语中的指针)

    如果我使用带有频繁append()s的ArrayList(就像我们手头的例子一样),会怎么样?是否仅复制阵列,而不复制阵列中的对象

    阵列仅在需要调整大小时才被复制,即很少复制,且摊销成本与插入数成比例。引用的对象永远不会被复制

    另外,当复制数组时,即使旧数组是终身的,新数组也会从伊甸园开始,对吗

    对!

    但是在Java中,对象数组不就是引用数组吗?即。 数组中的每个对象以及数组对象本身都是 在内存中分离并被垃圾收集器视为分离

    我觉得有点混乱,因为在C中:

  • 有可能有一个真正存储结构的结构数组
  • 也可以有指向结构的指针数组
  • 我很确定Java总是使用1。对于基元类型的数组和 总是使用2。对于对象数组,而C可以对任何 类型

    与C一样,Java通常将基元类型的数组存储为具有这些类型元素的实际数组。因此,一个包含10个元素的
    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:当然,分配器会将分配的对象放在相邻的行中(除非它自己必须获得新的内存块)。但是接下来的是。。。它也试图保留地方性,但它变得更加复杂。有时这可能是一个问题,但不要忘记。通常我同意过早优化的概念,但当涉及到日常结构和数据的邻接性时。。嗯,从磁盘读取是很慢的。这是大多数编程的瓶颈。。基本上,任何在合成中不是很重的东西。。。(我毫不犹豫地说