2012-07-10 151 views
7

那么,我已经开发了一个java应用程序使用几个对象的关系,使内存使用过于昂贵。我没有管理Java内存的经验,因为应用程序设计使得难以销毁对象并重新利用先前清除的空间。例如,我正在使用Observer和MVC模式。如何销毁java对象?

所以,理论上说..

一个物体变得符合垃圾收集或GC从任何活动线程或任何静态参考

换句话说,如果它不是 到达你可以说如果一个对象的所有引用都为null,那么这个对象就有资格进行垃圾回收。

但是,在我短暂的经历中,对于我来说,当你有像我这样的场景时,我想从内存中删除所有从内存中删除的对象的引用(例如,当一个框架关闭时)不知道你的类有多少个引用存在。

根据这种情况,当有多个引用时,我该如何处理对象破坏?或者当你有彼此复杂的引用时,如何管理内存?

回答

17

跟踪

根据这种情况下,我该怎么处理时,有它的倍数引用对象的破坏?

通过确保这些参考不再需要。

如果孤立他们,甚至不再连接到主编程'未使用的对象的一大孤立的图形,然后他们都是符合垃圾收集

已到达其作用域末端的局部变量将有资格进行垃圾回收(如果它们包含的)对象,如果它们没有被“链接到”其他任何东西(添加到集合,ac omposite等等...)。对于UI对象来说,确实很难用对象图推理,所以请确保正确处理它们或阅读文档以确保它们自然处理。

Simplified View of Reference Counting in the JVM

“离开[GC]当家!”

或者当您有复杂的相互引用时,如何管理内存?

您无法“管理”内存。您可以简单地管理参考。这个想法是通过简单地没有对它们的引用来“严重”到你的对象的连接。然后他们一直记忆直到GC消灭他们。

不要企图惹GC强迫它做事情。这是一个相当聪明的野兽,而你可以尝试指示它在一定请求明确反应 - 这可能不理你了 - 这是usually a bad ideado not invoke the GC explicitly,避免终结和explicit nullingif you don't understand their implications


注回答您的评论

简单归零一个引用已添加到多个集合或复合材料不会使它符合回收的对象。通过这样做,you'd have only nulled one reference

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

也许它听起来很乏味,但如果你从手动管理内存的语言中想到它(C或C++,要命名最多两个明显的引用),那么将free-ing和null-ing指向动态分配的对象确实会销毁它们,但是您仍然需要从列表(或任何容器)中删除该元素,否则它们将显示为空的存储桶以空指针。


进一步阅读

+0

了解!但是......如何在可以添加(例如)多重数组列表时添加一个对象?设置'object = null'会删除所有引用? – manix 2012-07-10 00:21:33

+1

@manix:不,它不会。那只会在当前范围内将名为'object'的引用置空。您需要从所有这些列表或任何其他容器中删除此对象。 – haylem 2012-07-10 00:23:07

+0

@halem多重阵列列表是短命还是长命?如果他们短暂,那么没有问题。在ArrayList不再可及之后,垃圾收集器将发挥它的魔力。如果数组列表长期存在,那么它的所有元素都将在其生命周期内可到达,除非你做了一些事情。我建议短命阵列列表。 – emory 2012-07-10 00:26:47

6

java垃圾收集的关键在于你不必做任何事情。垃圾收集已完成。

+0

Nuff说大声笑。另外,就你而言,我明白你为什么担心。但是这样想,或者真的有两种情况。 1,创建你正在使用的任何代码的开发人员并没有记录潜在的内存泄漏,在这种情况下,除了使用其他内容外,没有什么可以做的。 2,你阅读解释这个文件,并帮助你避免任何问题,如你所说的。所以通常不要担心它太多,除非您怀疑某些代码会降低您的应用程序的速度。 – Andy 2012-07-10 00:14:18

+0

如何使用@Martinsos的“代理”方法说?为了删除其参考 – manix 2012-07-10 00:27:40

1

将您希望GC收集的每个参考文献分配到null

+0

做同样的事情,如果obj包含运行线程对象或计时器? – suiwenfeng 2015-11-24 02:39:23

1

你可以做的是做一个中级班。例如,如果你有类A的实例,为此你有很多引用,并且你想删除它,但是很多引用使得它很难,你可以执行以下操作:创建B类的实例,其中除了参考A类的实例(如某种代理)。现在,您将有很多对B类实例的引用,但只有一个对类A实例的引用,您可以轻松地将其删除,垃圾收集器将收集类A的实例。

图片显示使用代理时的差异(B类实例):现在只有一个引用必须被删除。

enter image description here

+0

有帮助!现在更清楚:) – manix 2012-07-10 00:46:29

0

在大多数情况下,GC将做它的好时机魔法。

您可能会出现这样一种情况,即某个视图正在观察模型,而您想要放弃视图但保留该模型。在这种情况下,您需要记住观察者回调对象,并在抛弃视图时将其删除。你不必为每个观察者都有特殊的字段 - 一组注销回调的任务都没问题。或者,更复杂的是,您可以在从底层解压缩的模型上有一层瞬态间接寻址。我建议避免奇怪的东西与弱的参考某种或另一种。

如果您可能有终结者(或需要某种弱地图驱逐),例如推测使用java.awt.Frame,则可能需要资源和内存猪之间的间接层,它可以简单地被清除。