7

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

所以,理论说..

如果无法从任何活动线程或任何静态引用访问对象,则该对象有资格进行垃圾收集或 GC

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

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

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

4

5 回答 5

17

注意动向

根据这种情况,当有多个引用对象时,我该如何处理对象破坏?

通过确保不再需要这些引用。

如果你隔离它们,即使在一个不再连接到你的主程序的未使用对象的大隔离图中,它们都可以进行垃圾收集

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

JVM 中引用计数的简化视图

“别管[GC]!!”

或者当您对彼此有复杂的引用时,我需要如何管理内存?

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

不要试图弄乱 GC 来强迫它做事。这是一个相当聪明的野兽,虽然你可以尝试指示它明确地对某些请求做出反应- 它可能会忽略你 - 这通常是一个坏主意不要显式调用 GC,避免终结器和显式空值 ,如果你不明白他们的影响


注意回答您的评论

简单地将对已添加到多个集合或组合中的对象引用置空不会使其符合收集条件。通过这样做,您只会取消一个引用

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

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


延伸阅读

于 2012-07-10T00:14:29.837 回答
6

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

于 2012-07-10T00:11:56.440 回答
1

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

于 2012-07-10T00:14:32.873 回答
1

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

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

在此处输入图像描述

于 2012-07-10T00:16:34.607 回答
0

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

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

如果您可能有终结器(或需要某种弱映射驱逐),例如可能使用 java.awt.Frame,您可能希望在资源和内存猪之间有一层间接层,可以简单地将其清空。

于 2012-07-10T00:42:15.803 回答