如何破坏java对象?

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

所以,理论说……

如果从任何活动线程或任何静态引用无法访问对象,则该对象符合垃圾收集或GC的条件

换句话说,如果对象的所有引用都为null,则可以说对象符合垃圾回收的条件。

但是,根据我的短暂经验,当我有一个像我这样的场景,你不知道如何从我想要从内存中移除的对象(例如,当一个框架关闭时)销毁所有引用时,对我来说太难了存在许多对类的引用。

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

注意动向

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

确保不再需要这些参考。

如果你将它们隔离开来 ,即使在一个大的孤立图表中,未使用的对象也不再连接到你的主程序, 那么它们都有资格进行垃圾收集

已达到其范围末尾的局部变量将有资格进行垃圾收集(以及它们包含的对象),如果它们尚未“链接”到任何其他对象(添加到集合,交互式等等) 。 对于在对象图方面确实难以推理的UI对象,请确保正确处理它们或阅读文档以确保它们自然处理掉。

JVM中引用计数的简化视图

“让[GC]独自!!”

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

你无法“管理”记忆。 您可以简单地管理参考。 我们的想法是通过简单地不引用它们来“严格”与对象的连接。 然后它们会在内存中存活,直到GC消灭它们为止。

不要试图弄乱GC来强迫它做事。 它是一个相当聪明的野兽,虽然你可以尝试指示它明确地对某些请求作出反应 – 它可能会忽略你 – 这通常是一个坏主意 : 不要显式调用GC , 如果你不理解则避免使用终结器和显式置零 它们的含义 。


请注意回答您的评论

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

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

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


进一步阅读

  • 垃圾收集 (特别是关于可达性的部分)
  • Sun Microsystems在Java HotSpot虚拟机上的白皮书 (已过时,但非常好)
  • Java理论与实践:垃圾收集简史 – 垃圾收集如何运作?
  • Java理论与实践:垃圾收集性能
  • 垃圾收集如何在Java中工作
  • 处理Java程序中的内存泄漏
  • 从Java代码到Java堆
  • 这些SO问题:
    • Java Memory Explained (提供了很多额外的信息和链接
    • Java内存管理最佳实践

java垃圾收集的重点是你不必做任何事情。 垃圾收集为您完成。

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

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

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

在此处输入图像描述

在大多数情况下,GC会在适当的时候做到这一点。

你可以有一种情况,比如说,一个视图正在观察一个模型,你想放弃视图但保留模型。 在这种情况下,您需要记住观察者回调对象,并在丢弃视图时将其删除。 您不必为每个观察者都有特殊字段 – 一组取消注册回调的任务都可以。 或者,更复杂的是,您可以在模型上有一层瞬态间接,从底层解压缩。 我建议用一种或另一种弱引用来避免奇怪的东西。

如果您可能有终结者(或需要某种弱映射驱逐),例如大概使用java.awt.Frame,您可能需要在资源和内存猪之间有一层间接,这可以简单地消除。