首页>Program>source

我是一名进入Java世界的C ++程序员.而且,我不能删除必须让Java垃圾收集器进行清理的不良感觉。

例如,此代码将如何在Java中运行?

public void myFunction() {
    myObject object = new myObject();
    object.doSomething();
}

当myFunction()退出时,是否将删除局部变量对象?

我是否必须在退出之前将对象设置为null,否则它将超出范围并被GC删除吗? 或者,在最坏的情况下,它会像在C ++中那样泄漏吗?

最新回答
  • 2021-1-11
    1 #

    在不再使用后的某个时候,它将在处被垃圾回收.我相信在Java的当前实现中,它实际上将一直保留到方法结束时,而.NET中的垃圾收集器则更具攻击性. (即使在Java中,我也不知道是否有任何保证。通常,您只想想要在调试时将本地变量保留到其上次可能读取的范围之外。)

    但是不,您不需要将变量设置为null,否则会损害可读性。

    方法退出后,对象不太可能立即立即进行垃圾回收; 这取决于GC的运行时间……而且,当然,如果有任何其他保留该对象的引用,则该对象可能仍不适合进行垃圾收集.不要忘记变量的值只是一个引用,而不是对象本身. (这可能需要一段时间才能习惯于C ++。)

  • 2021-1-11
    2 #

    GC至少在内存限制接近时才开始工作,因为超出范围的变量引用的任何对象都可以被垃圾回收, 但是最后一个退出的块存在超出范围的局部变量的意外行为。

    让我们来比较一下:

    {
       final List myTooBigList = new ArrayList();
       ... overfill the list
    }
    somethingRunOutOfMemory();
    

    somethingRunOutOfMemory() 因为 myTooBigList 不能使用GC,尽管范围不再可用,并且要求更多的内存,与以下不同:

    {
       final List myTooBigList = new ArrayList();
       ... overfill the list
    }
    Object fake = null;
    somethingDoesNotRunOutOfMemory();
    

    fake的影响 向后移动堆栈指针,让 myTooBigList GCable,然后只要内存限制接近,GC就会开始工作。 令人惊讶的是(至少在我正在测试的jvm中),我们必须在同一级别上显式地重用堆栈.可以预料到,一旦退出该块,局部变量就可以被GC使用,但是我认为这是对性能的一种折衷.这样会使字节码复杂得多。

    像C中一样,局部变量位于框架旁边的堆栈中。 堆栈指针为范围内的局部变量保留所需的空间。 重用堆栈时,{退出块}的局部变量变为GCable,即:在同一堆栈级别上声明局部变量之后,函数返回之后或退出评估(捕获,循环条件)之后。

    在:之后它们是可GC使用的

    try { } catch : after exit by catch because catch reuses stack
    for { } : after exit loop condition  because evaluation reuses stack
    while { } : after exit loop condition because evaluation reuses stack
    { } declare=value : after any declaration+affectation that reuses stack
    

    在:之后它们不能被GC使用

    try { } : after nothing caught
    for { } : after exit by break
    while { } : after exit by break
    do { }
    if { }
    { }
    

    注意:要进行实验,请运行GC,然后比较 WeakReference(my variable)null

    final WeakReference gctest;
    {
       final List myTooBigList = new ArrayList();
       gctest = new WeakReference(myTooBigList);
       ... overfill the list
    }
    Object fake = null;
    System.gc();
    assert gctest.get() == null;
    

  • 2021-1-11
    3 #

    它将超出范围.在Java中,当没有人再指向一个对象时,该对象将被垃圾回收,或者至少可用于垃圾回收.无需在此处将其设置为null.有时,如果您的对象将存在于您的App中,则需要将对象引用设置为null,但是需要对其进行保存的引用进行垃圾收集.在这种情况下,您选择释放参考。

相关问题

  • c#:PictureBox问题
  • c#:查询代码速度极慢,但SSMS快速