【问题标题】:Java - Do object references get destroyed when the creating class is closed?Java - 创建类关闭时对象引用会被破坏吗?
【发布时间】:2017-11-14 19:02:31
【问题描述】:

假设我有一个类,它加载一个文件,然后调用另一个方法对该文件执行某些操作。例如,计算文件中的单词。

在 CountWords 类中,创建了许多对象/集合以获取单词数。方法运行,找到字数,然后返回给调用类。

我的问题是,当控制权返回给调用类时,CountWords 类中创建的所有对象/集合是否都“销毁”了,或者它们是否保留在内存中?如果是后者,我是否必须在退出类之前将每个对象设置为 null 以将它们标记为收集?

【问题讨论】:

标签: java object garbage-collection jvm


【解决方案1】:

我们通常不会准确控制 Java 对象何时被销毁。它会在它变得不可访问后的一段时间内被销毁 - 换句话说,当在任何范围内都没有进一步引用它时。

如果您创建一个对象,并将对它的引用存储在另一个对象的字段中,那么只要具有该引用的对象可访问,您创建的对象就可以继续访问。

如果你有这样的代码

public void run() {
    Foo a = new Foo();
    System.out.println("This method is finished");
}

那么一旦run 完成,您创建的Foo 将无法访问,因为没有更多变量引用它。 Foo 将在一段时间后被销毁。当然,除非Foo 的构造函数做了一些魔术来将自己注册到某个讨厌的static 数据存储中。

因此,一般来说,您不需要将引用设置为 null 来销毁对象。从垃圾收集器的角度来看,让这些引用超出范围与将它们设置为 null 一样好。

【讨论】:

  • 至少有一个例外:如果一个对象仅被WeakReferencesPhantomReferences 引用(尽管PhantomReferences 并没有真正引用该对象),它就有资格进行垃圾回收。
  • @Turing85 这绝对是真的。我想我想避免一些讨厌的细节,但我不应该牺牲正确性。
【解决方案2】:

Java 是一种具有内存管理(即垃圾收集)的编程语言。基本答案是,垃圾收集器会负责回收未使用对象的内存。

但是,既然您已经用[garbage-collection] 标记了这个问题,那么您应该已经知道这一点。因此,不清楚您想知道哪些额外的细节,或者为什么您认为您的场景在任何方面都很特别,除了“有一个垃圾收集器”之外,还应该得到一个额外的答案。

您的问题充满了错误或误导性的短语。

  • 对象引用是否被销毁”——对象的存储被回收,没有“引用的销毁”之类的东西

  • 当创建类关闭时”——没有所谓的“类关闭”

  • 当控制权返回给调用类时,CountWords 类中创建的所有对象/集合会被‘销毁’还是保留在内存中?”——在这种形式中,并不简单回答

    • 没有所谓的“破坏”。垃圾收集的全部目的是允许内存的重用。这意味着在内存空闲的地方记录。但内存本身不需要被触动。
    • 当您的方法返回时,这些对象有资格进行垃圾回收。垃圾收集本身不必立即运行。当需要空闲内存或 CPU 负载较低时,可能会发生这种情况。
    • 如前所述,即使垃圾收集器运行,结果是内存现在被认为是空闲的,不一定要“清理”内存。因此对象可能“保留在内存中”,直到实际被其他对象覆盖。所以这简直是个错误的问题。您实际上想知道内存是否可重复使用。
  • 如果是后者,我是否必须在退出类之前将每个对象设置为 null 以将它们标记为收集?”——“后者”在语义上仍然意味着内存是空闲的。但是你想“设置为null”什么呢?引用不再存在。对象无法访问。

    答案是你无能为力,也没有什么是你应该做的。这就是垃圾回收的全部意义所在,您无需做任何事情。

【讨论】:

  • 虽然我很欣赏我在 Stack Overflow 上收到的所有回复,但我对您的回复特别感到有些恼火。从我的声誉中可以清楚地看出我是一名业余程序员,所以我从业余爱好者的角度提出问题并非不可想象。再次感谢您的回复,但下次对新手要温和一点 - 记住您曾经是一个人!
  • 这与您的知识或您是否是初学者无关。这是关于提出一个精确的问题。如前所述,您显然知道通过正确标记您的问题所显示的垃圾收集器的存在。我们无法猜测您知道哪些事实以及您不清楚哪些事实,因此您必须在您的问题中澄清它。顺便说一句,Stackoverflow 的声誉并不能说明您的编程技能,而只能说明您在 Stackoverflow 上的历史。
【解决方案3】:

函数出来后我们不需要将对象设置为null。对于这个 Java 有垃圾收集器,它运行在 Java 虚拟机上,它摆脱了 Java 应用程序不再使用的对象。它是一种自动内存管理的形式。

例如:

for (int i =0 ; i<10 ; i++) {
    String s = String.valueOf(i)
}

在上面的代码中,整数 s 是在 for 循环的每次迭代中创建的。这意味着在每次迭代中,都会分配一点内存来创建一个整数对象。

回到代码,我们可以看到,一旦执行了一次迭代,在下一次迭代中,在前一次迭代中创建的整数对象就不再被使用——该对象现在被认为是“垃圾” .

最终,我们将开始获得大量垃圾,并且内存将用于不再使用的对象。如果这种情况持续下去,最终 Java 虚拟机将耗尽空间来创建新对象。

这就是垃圾收集器介入的地方。

垃圾收集器会寻找不再使用的对象,并删除它们,释放内存以便其他新对象可以使用那块内存。

像垃圾回收这样的自动内存管理方案使程序员不必担心内存管理问题,因此他或她可以更专注于开发他们需要开发的应用程序。

【讨论】:

  • 我不确定这是否完全正确。 int 不是 对象。您的示例中的 int 变量 s 不在堆上,因此它不是垃圾收集的。当它超出范围时,它就不再存在了。
  • 如果循环体类似于String s = String.valueOf(i),答案将是完全正确的。
猜你喜欢
  • 2020-03-05
  • 1970-01-01
  • 2015-05-24
  • 2010-12-25
  • 2018-02-26
  • 1970-01-01
  • 2013-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多