首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >哪个对象将被垃圾收集?

哪个对象将被垃圾收集?
EN

Stack Overflow用户
提问于 2010-01-20 06:03:20
回答 3查看 393关注 0票数 1

我想确认哪个场景会导致对象myObj上的垃圾收集:

场景1

代码语言:javascript
运行
复制
ArrayList arList = new ArrayList();
while(someCondition)
{
  myObj = new MyObect(); // a custom object
  arList.add(myObj); 
}

场景2

代码语言:javascript
运行
复制
ArrayList arList = new ArrayList();
while(someCondition)
{
  myObj = new MyObect(); // a custom object
  arList.add(myObj); 
  myObj=null;
}

显式地将对象设置为null是否会改善垃圾收集行为,还是在使用新构造函数重置对象时会是相同的?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-01-20 06:08:15

您没有指定myObj的范围及其重要性。如果它是一个局部变量,那么它几乎肯定无关紧要。如果它是一个实例变量,那么这可能是一个长期存在和不必要的引用,在这种情况下,设置为null将是有用的。

更新:给出了更新后的信息,即myObj是该方法的本地信息,在循环每次迭代结束时将其设置为null是零值。考虑一下这个例子:

代码语言:javascript
运行
复制
public void process(String text) {
  String[] lines = text.split("\n");
  List<MyObject> list = new ArrayList<MyObject>();
  Object myObj;
  for (String line : lines) {
    myObj = new MyObject(line);
    list.add(myObj);
    // 1. set myObj = null here
  }
  list = null; // 2
  // 3. do some other stuff
}

public class MyObject {
  private final String line;

  public MyObject(String line) {
    this.line = line;
  }
}

在这个例子中,假设在第3步,它花费了很长的时间。说十分钟吧。在这10分钟内,myObj指向处理的最后一行。听起来不像是个问题?有可能是这样。在Java中,子字符串的工作方式是引用原始字符串。所以如果你这么做了:

代码语言:javascript
运行
复制
String s = ... // 100 megabytes
String s2 = s.substring(100, 101);

实际上,您将整个100 s2保存在内存中,因为s2引用了s。

因此,在我前面的函数中,myObj引用了一行引用整个文件的行。将步骤1更改为myObj = null;实际上会有所帮助,因为此引用将防止垃圾收集对象。

注意:步骤2在这里很重要,因为如果您不取消列表,那么所有引用都会存在。

你只需要考虑一下引用是如何工作的。当对对象的引用存在时,它不会被垃圾收集。这意味着清除长期存在的引用并尽可能严格地保持变量的作用域。解决上述问题的正确办法是:

代码语言:javascript
运行
复制
for (String line : lines) {
  Object myObj = new MyObject(line);
  ...
}

然后,myObj在循环中被限定范围,所以当循环结束或另一个迭代开始时,它已经超出了范围,这要好得多。

票数 7
EN

Stack Overflow用户

发布于 2010-01-20 06:07:11

将其设置为null不会有任何效果,因为通过arList对象仍然是可达

也就是说,您的MyObect实例将至少与arList一样长。

编辑:根据您的评论,myObj听起来确实更长寿。在这种情况下,在循环结束后将其设置为null

票数 6
EN

Stack Overflow用户

发布于 2010-01-20 06:29:21

我认为这是你误解的根源。

嗯..。但我不希望保留两个myObj副本,一个在arList中,一个在原始变量中。一旦我将myObj添加到arLsit中,如何冲洗它?

你不能“保留两份myObj”。在您的示例中,循环创建的每个MyObject实例只有一个“副本”。顺序如下:

  1. 创建一个MyObject实例,将其引用分配给myObj
  2. 将对实例的引用添加到arList引用的arList
  3. null分配给myObj中的引用。

请注意,将引用添加到列表并不会创建MyObject实例的副本。它仅仅意味着你在两个地方而不是一个地方有引用。当您分配null时,您将再次将引用放在一个位置上。

另外要注意的是,将null分配给某物永远不会导致垃圾收集器运行。它所做的就是(显式地)在下次运行垃圾收集器时从考虑中删除引用的潜在副本。

最后,如果我们假设范围如下,则C行将没有明显的效果.除非A行或B行触发垃圾回收。

代码语言:javascript
运行
复制
{
    MyObject myObj;
    ArrayList arList = new ArrayList();
    while (someCondition) {       // A
         myObj = new MyObect();   // B
         arList.add(myObj); 
         myObj = null;            // C
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2099354

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档