如何使垃圾收集器在超出范围之前处理它?

时间:2017-08-29 14:47:09

标签: c# .net garbage-collection

我知道当堆栈中不再有对象时,GC会清理堆上的对象。

我想知道是否有办法迫使GC在此之前采取行动。我的情景是这样的。

@RealmClass
public class TripStop extends RealmObject implements Serializable {
@Nullable
private int arrival_time;
private String address;
@PrimaryKey
private int id;
@Nullable
private int departure_time;
private Destination place;
private CoordLocation location;

public int getArrival_time() {
    return arrival_time;
}

public void setArrival_time(int arrival_time) {
    this.arrival_time = arrival_time;
}

public String getAddress() {
    return address;
}

public void setAddress(String address) {
    this.address = address;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public int getDeparture_time() {
    return departure_time;
}

public void setDeparture_time(int departure_time) {
    this.departure_time = departure_time;
}

public Destination getPlace() {
    return place;
}

public void setPlace(Destination place) {
    this.place = place;
}

public CoordLocation getLocation() {
    return location;
}

public void setLocation(CoordLocation location) {
    this.location = location;
}
}

我希望在调用foobar()之前我可以释放集合使用的内存。有没有办法做到这一点?

ps。:我知道这是一个糟糕的代码,但它是一个遗留代码,我现在无能为力。

更新:正如InBetween所指出的那样,“GC被允许收集任何不可修复的对象,但它不会确定它会这样做”。不幸的是,我有一些用户的内存要求,应用程序必须将其内存使用量保持在一定限度内,否则我通常会让GC完成其工作。

2 个答案:

答案 0 :(得分:3)

  

我知道当堆栈上的对象不再引用它们时,GC会清理堆上的对象。

事实并非如此:

var o = new object();
return new[] { o }

好的,这个方法返回后,堆栈上o的引用究竟在哪里?

以这种方式更好地考虑它:如果GC可以证明它不再可以访问,那么任何对象都有资格收集。这与你声称的完全不同。

此外,如果GC可以证明不会再次读取对给定对象的引用,那么即使存在可访问的引用,也可以收集该对象(因为它从未被使用过,因此它不会被使用。和无法到达一样好。)

当GC确定这是一个好时机时,GC会为您执行这两种方案;它比你好得多,所以让它完成它的工作,不要担心它。在极少数情况下,您必须干扰GC的工作方式。

答案 1 :(得分:2)

在3种情况下调用.NET中的垃圾收集:

  1. 分配超过第一代(第0代)或大对象堆阈值
  2. 系统内存不足,
  3. 致电bottomnavigationview方法
  4. 根据您的"代码"判断我可以猜测它将在第一种情况下被调用,在这种情况下(因为你仍然有对该对象的引用)我建议你把它包装到其他一些代码块中。例如:

    GC.Collect

    如果这不可能,那么只需尝试取消引用public void A () { DoSomethingWithTheList(); foobar(); //more code before it goes out of scope } private void DoSomethingWithTheList() { IList foo = bar(); //does work on foo's items } 对象,方法是将其设置为IList,然后调用具有最高代null作为参数的GC.Collect诀窍。

    public void A ()
    {
        IList foo = bar();
        //does work on foo's items
        foo = null;
        GC.Collect(2, GCCollectionMode.Forced); // force GC
        foobar();
        //more code before it goes out of scope
    }
    

    这假设IList foo中的对象未在其他地方引用