这种形式的内存管理在Java中有意义吗?

这种形式的内存管理在Java中有意义吗?,java,memory-management,memory-leaks,garbage-collection,Java,Memory Management,Memory Leaks,Garbage Collection,在应用程序的生命周期中,我必须重新创建一个ArrayList,其中包含对象的其他ArrayList(从存储器中读取)。ArrayList始终分配给类中的同一数据成员,基本上使ArrayList中较旧的ArrayList悬空(不可引用或不可访问) 我的理解是,与C++不同,这不会导致内存泄漏,因为系统知道对象何时变得不可引用,并且在适当的时候释放内存。 不过,旧习惯很难克服,我几乎本能地被吸引到“帮助”系统,在重新创建ArrayList of ArrayList之前,我自己做了一些清理工作: fo

在应用程序的生命周期中,我必须重新创建一个ArrayList,其中包含对象的其他ArrayList(从存储器中读取)。ArrayList始终分配给类中的同一数据成员,基本上使ArrayList中较旧的ArrayList悬空(不可引用或不可访问)

<>我的理解是,与C++不同,这不会导致内存泄漏,因为系统知道对象何时变得不可引用,并且在适当的时候释放内存。 不过,旧习惯很难克服,我几乎本能地被吸引到“帮助”系统,在重新创建ArrayList of ArrayList之前,我自己做了一些清理工作:

for (InnerArray aList : outerArray)
  aList.clear();
outerArray.clear();
我的问题是:

  • 这是多余的吗
  • 我做的弊大于利吗
  • 这有什么好处吗
  • 为什么?

  • 这是多余的。您并没有帮助释放这些对象,因为垃圾收集已经确定它们是不可访问的。你不能让他们比现在更难以接近。所以,你会浪费一点处理时间在一些什么也做不到的事情上

    不过,主要的问题是,您让其他开发人员感到困惑,他们会想知道您为什么要清除该阵列。他们可能会浪费时间试图弄明白你为什么这么做,如果有一些隐藏的原因,他们一开始没有看到的话

    <>一个类似的问题,C++开发者倾向于使用java代码;在Java中,您几乎不想这样做,因为终结器会给垃圾收集增加额外的成本,而且它们不是释放资源的可靠方法,因为它们可能在很长一段时间内或永远不会被调用

  • 是的,老实说,我就是不明白。如果你不再需要一个对象,只要确保你不能再访问它,你就很好
  • 是的,调用可能会使用处理能力,垃圾收集可能会使用更少的处理能力来摆脱对象。正如内特所说,这可能会让人困惑
  • 没有,对不起,我没看到什么好东西
  • 请参见上文,欢迎使用Java!你现在可以专注于有趣的事情了:)
  • 另外,我不确定我现在要说什么,但是
    clear()
    函数可以从
    ArrayList
    中删除元素,只需确保您不能再通过
    ArrayList
    变量访问它们。也许它不会“摧毁”它们,但它只会使它们符合垃圾收集的条件。很高兴知道该函数是如何实现的

    另外,你可能会想自己调用GC,不要这样做!看

    编辑:

    以下是
    ArrayList
    中的
    clear()

    public void clear()
    {
        if (size > 0)
        {
            modCount++;
            // Allow for garbage collection.
            Arrays.fill(data, 0, size, null);
            size = 0;
        }
    }
    
    1) 这是多余的吗

    2) 我做的弊大于利吗

    3) 这有什么好处吗

    没有

    4) 为什么?

    ArrayList
    上调用
    clear()
    会更改列表的
    size
    字段,然后小心地将
    null
    分配给其支持数组中刚刚变为无效的元素。
    clear()
    的代码需要这样做,因为这些元素中的引用可能会导致其他对象保持可访问性;i、 泄漏内存

    但是,当
    ArrayList
    变得不可访问时,垃圾收集器将不再查看备份数组的任何元素。GC的标记过程只遍历可访问对象,回收过程不查看垃圾对象/数组的内容

    因此,基本上,对一个即将无法访问的对象调用
    clear()
    ,完全是对CPU周期和内存/VM带宽的浪费。(当然,这是多余的代码,下一个家伙会挠头……)


    事实上,调用
    clear
    然后重用列表是否是一个好主意甚至还有争议:

    • 调用
      clear
      不会释放/调整备份数组的大小,因此对于通常较小的列表,您可能会留下一个巨大的备份数组

    • 垃圾收集器可以释放足够大的数组,并以比
      clear()
      更快的速度分配相同大小的新数组,这是不可想象的。(首先,GC可以使用多个处理器,其中对
      clear()
      的调用将在一个线程上运行。)

    是否有一种场景可以证明调用clear()是正确的

    清除/重用列表绝对必要的唯一情况是,其他内容引用了该特定列表,而您无法更新列表引用


    在内存受限和/或GC速度较慢的平台上清除/重用列表也可能有好处。然而,除非我有强有力的证据证明这是一个问题,否则我不会尝试这种“优化”。(这种优化会使您的代码更加复杂,如果操作不当,可能会导致性能问题。)

    感谢+1提供的启发性答案。我将等待更多的答案以获得更多的见解。这里有一篇短文解释了Java类型GC的基本工作原理,它可能有助于为您澄清一些事情:“很高兴知道该函数是如何实现的…”阅读源代码Luke。@Gevorg-“该死,如果我太懒了”回过头来看您:-)确认!clear()只会使列表中的对象符合垃圾收集的条件。请参阅下面我编辑的答案。谢谢+1。根据您的解释,需要尽可能避免调用clear()。是否有一种情况可以证明调用clear()是正确的?您的ArrayList保存了您最喜欢的CD,但有人偷走了它们!所以你清除了()你的ArrayList,你就没有CD了(不涉及内存管理)@斯蒂芬:你说“回收过程不看垃圾对象/数组的内容”是什么意思?如果数组列表(a