【问题标题】:How to destroy java objects?如何销毁java对象?
【发布时间】:2012-07-09 10:28:44
【问题描述】:

好吧,我已经开发了一个 java 应用程序,它使用了多个对象关系,这使得内存使用成本太高。我没有管理 java 内存的经验,因为应用程序设计使得很难销毁对象并重新利用以前清除的空间。例如,我正在使用 Observer 和 MVC 模式。

所以,理论上是这样说的..

如果一个对象不符合垃圾收集或 GC 的条件,则该对象有资格 可从任何活动线程或任何静态引用访问

换句话说,如果一个对象的所有引用都为空,你可以说它有资格进行垃圾回收。

但是,在我短暂的经验中,当你遇到像我这样的场景时,我很难销毁我想从内存中删除的对象的所有引用(例如,当框架关闭时)不知道有多少对你的类的引用。

根据这个上下文,当对象被多个引用时,我该如何处理它?或者当您对彼此有复杂的引用时,我需要如何管理内存?

【问题讨论】:

    标签: java memory memory-management garbage-collection


    【解决方案1】:

    Java 垃圾收集的全部意义在于您无需执行任何操作。垃圾收集已为您完成。

    【讨论】:

    • 纳夫说哈哈。另外,在你的情况下,我明白你为什么担心。但是这样想,或者真的有两种情况。 1,创建您正在使用的任何代码的开发人员不会记录潜在的内存泄漏,在这种情况下,除了使用其他东西之外您无能为力。 2,您阅读了解释这一点的文档,并帮助您避免出现您所说的任何问题。所以一般不用太担心,除非你怀疑某些代码会拖慢你的应用程序。
    • 使用@Martinsos 所说的“代理”方法怎么样?为了删除它的引用
    【解决方案2】:

    跟踪

    根据这个上下文,当对象被多个引用时,我该如何处理它?

    确保不再需要这些引用。

    如果您将它们隔离,即使在未连接到您的主程序的未使用对象的大隔离图中,那么它们都可以进行垃圾收集。。 p>

    如果局部变量没有被“链接”到其他任何东西(添加到集合、复合等),则已达到其范围末尾的局部变量将有资格进行垃圾收集(它们所包含的对象也是如此)。 ..)。对于 UI 对象,确实很难根据对象图进行推理,请确保正确处置它们或阅读文档以确保它们会自然处置。

    “让 [GC] 一个人呆着!!”

    或者当你有一个复杂的相互引用时我需要如何管理内存?

    您无法“管理”内存。您可以简单地管理参考。这个想法是通过简单地不引用它们来“切断”你与对象的连接。然后它们会一直存在于内存中,直到 GC 将它们消灭。

    不要试图弄乱 GC 来强迫它做事。它是一只相当聪明的野兽,虽然你可以尝试指示它明确地对一些请求做出反应 - 它可能会忽略你 - 它是 usually a bad idea: do not invoke the GC explicitly,避免终结者和explicit nulling if you don't understand their implications


    注意回答您的评论

    对已添加到多个集合或组合的对象的 a 引用简单地置空不会使其符合收集条件。通过这样做,you'd have only nulled one reference

    您确实需要从所有引用它的列表或容器中删除该对象(基本上,让他们“忘记”这个对象)。一旦没有对象仍然“记住”或与您创建的对象有“链接”,它就会在垃圾收集器的图表中成为一个孤立的项目,这使其成为删除的候选对象。

    也许这听起来很乏味,但是如果您从手动管理内存的语言(C 或 C++,以命名最明显的两个引用)来考虑它,则释放和空指针指向您的动态分配的对象会确实会销毁它们,但您仍然需要从列表(或任何容器)中删除元素,否则它们看起来就像指向空指针的空桶。


    进一步阅读

    【讨论】:

    • 明白!但是...当可以将对象添加(例如)在多个数组列表中时,如何隔离它?设置object = null 将删除所有引用?
    • @manix:不,不会。这只会使当前范围内名为 object 的引用无效。您确实需要从所有这些列表或任何其他容器中删除此对象。
    • @halem 多个数组列表的寿命是短的还是长的?如果它们是短暂的,那么就没有问题。在不再访问 arraylist 后,垃圾收集器将发挥它的魔力。 OTH 如果 arraylist 是长期存在的,那么它的所有元素在其生命周期内都将是可访问的,除非你做某事。我推荐短命的数组列表。
    • @emory:是的,但是我的回答中已经涵盖了短暂的方面:本地对象将有资格被收集,因此将成为它们包含的引用(如果在其他任何地方都没有的话)。这是引用计数的多米诺骨牌效应。
    • @manix:因为您似乎是新手...如果这个答案(和其他人)帮助您并回答您的问题,您应该投票赞成他们(使用每个答案左侧的向上指向)并接受最正确回答您问题的那个(使用每个答案左侧的“勾号”符号)。不是说你需要知道,你当然可以给自己时间做出决定并等待更多答案。
    【解决方案3】:

    将您希望 GC 收集的每个引用分配给 null

    【讨论】:

    • 如果obj包含正在运行的线程对象或Timer,做同样的事情吗?
    【解决方案4】:

    你可以做的是做一个中间类。例如,如果你有一个类 A 的实例,你有很多引用并且你想删除它,但是很多引用使它变得困难,你可以执行以下操作:创建类 B 的实例,其中不包含任何其他引用 A 类的实例(如某种代理)。现在您将有很多对 B 类实例的引用,但只有一个对 A 类实例的引用,您可以轻松删除它,垃圾收集器将收集 A 类实例。

    使用代理(B 类的实例)时图像显示差异:现在只需删除一个引用。

    【讨论】:

      【解决方案5】:

      在大多数情况下,GC 会适时发挥它的魔力。

      您可能会遇到这样的情况,例如,视图正在观察模型,而您想放弃视图但保留模型。在这种情况下,您需要记住观察者回调对象,并在您丢弃视图时将其删除。您不一定必须为每个观察者设置特殊字段 - 一组取消注册回调的任务就可以了。或者,更复杂的是,您可以在模型上设置一层瞬态间接层,该层从底层解压缩。我建议避免使用某种弱引用的怪异事物。

      如果您可能有终结器(或需要某种弱映射驱逐),例如可能使用 java.awt.Frame,您可能需要在资源和内存消耗之间建立一层间接层,这可以简单地是无效。

      【讨论】: