Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.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_Performance_Memory Management_Garbage Collection_Jvm - Fatal编程技术网

垃圾收集会改变Java中的对象地址吗?

垃圾收集会改变Java中的对象地址吗?,java,performance,memory-management,garbage-collection,jvm,Java,Performance,Memory Management,Garbage Collection,Jvm,我读到垃圾收集会在运行时导致内存碎片问题。为了解决这个问题,压缩由JVM完成,它获取所有活动对象并为它们分配连续内存。 这意味着对象地址必须随时更改?而且如果发生这种情况, 对这些对象的引用是否也重新指定 这不会导致严重的性能问题吗?Java是如何应对的 如果你在内存中移动一个对象,它的地址就会改变。因此,需要更新指向它的引用。当连续(内存中)对象序列中的对象被删除时,会发生内存碎片。这在内存空间中造成了一个洞,这通常是不好的,因为连续的内存块具有更快的访问时间和更高的匹配查切线的概率,等等。应

我读到垃圾收集会在运行时导致内存碎片问题。为了解决这个问题,压缩由JVM完成,它获取所有活动对象并为它们分配连续内存。 这意味着对象地址必须随时更改?而且如果发生这种情况,

  • 对这些对象的引用是否也重新指定
  • 这不会导致严重的性能问题吗?Java是如何应对的

  • 如果你在内存中移动一个对象,它的地址就会改变。因此,需要更新指向它的引用。当连续(内存中)对象序列中的对象被删除时,会发生内存碎片。这在内存空间中造成了一个洞,这通常是不好的,因为连续的内存块具有更快的访问时间和更高的匹配查切线的概率,等等。应该注意的是,使用间接表可以防止引用更新达到所使用的最大间接级别

    垃圾收集的性能开销适中,不仅在Java中,在其他语言中也是如此,例如C#。Java如何应对这种情况,执行垃圾收集的策略以及如何最大限度地减少其对性能的影响取决于所使用的特定JVM,因为每个JVM都可以随心所欲地实现垃圾收集;唯一的要求是它符合JVM规范

    但是,作为一名程序员,您应该遵循一些最佳实践,以充分利用垃圾收集并将其对应用程序的性能影响降至最低。见、和。你可能想检查一下,但它有点密集

    我读到垃圾收集会在运行时导致内存碎片问题

    这不是垃圾收集堆的唯一问题。当您有一个手动管理的堆,并且以与前面分配不同的顺序释放内存时,您可能也会得到一个碎片堆。能够拥有与自动存储的后进先出顺序(又称堆栈内存)不同的生命周期,是使用堆内存的主要动机之一

    为了解决这个问题,压缩由JVM完成,它获取所有活动对象并为它们分配连续内存

    不一定是所有对象。典型的实现策略将内存划分为逻辑区域,并且一次只将对象从一个特定区域移动到另一个区域,而不是所有现有对象。这些策略可能包括物体的年龄,如世代收集器将年轻一代的物体从伊甸园空间移动到幸存者空间,或剩余物体的分布,如“垃圾优先”收集器,其将如名称所示,首先排出垃圾率最高的碎片,这意味着获得可用连续内存块的最小工作量

    这意味着对象地址必须随时更改

    当然,是的

    而且如果发生这种情况,

  • 对这些对象的引用是否也重新指定
  • 该规范没有规定如何实现对象引用。间接指针可以消除调整所有引用的需要,另请参见。然而,对于使用直接指针的JVM来说,这确实意味着这些指针需要调整

  • 这不会导致严重的性能问题吗?Java是如何应对的
  • 首先,我们必须考虑我们从中得到了什么。“消除碎片化”本身并不是目的。如果我们不这样做,我们必须扫描可访问对象之间的间隙,并创建一个维护这些信息的数据结构,我们称之为“空闲内存”。我们还需要实现内存分配,以搜索此数据结构中的匹配块,或者在没有找到精确匹配的情况下分割块。与连续空闲内存块的分配相比,这是一个相当昂贵的操作,在连续空闲内存块中,我们只需按所需大小将指针移动到下一个空闲字节

    考虑到分配比垃圾收集更频繁,垃圾收集只在内存已满(或超过阈值)时运行,这已经证明了更昂贵的复制操作的合理性。它还意味着只使用更大的堆可以解决性能问题,因为它减少了所需的垃圾收集器运行的数量,而幸存对象的数量不会随着内存的增加而增加(不可访问的对象保持不可访问状态,无论您延迟收集多长时间)。事实上,推迟收集会增加同时无法访问更多对象的可能性。也与之相比


    调整引用的成本并不比标记阶段遍历引用的成本高得多。事实上,非并发收集器甚至可以将这两个步骤结合起来,在第一次遇到对象时传输对象,然后调整随后遇到的引用,而不是标记对象。实际的复制是更昂贵的方面,但如上所述,通过不复制所有对象,而是使用基于典型应用程序行为的特定策略(如分代方法或“垃圾优先”策略)来减少所需的工作量。

    引用不必更新。可以有一个间接表。@user207421是的,为了完整起见添加了它。