java - 多次调用finalize

标签 java garbage-collection finalize

我尝试编写一个类来计算内存中实例的数量。我使用了静态属性 - 我在构造函数中递增它并在 finalize 方法中递减它。

您可以在下面看到 Counter 类。

在主类(TestCounter)上,我制作了计数器列表。当我用小值(java TestCounter 10 100)测试此类时,结果似乎正常:

Size of the list : : 0
curently : 100 over 100 created
Size of the list : : 0
curently : 200 over 200 created
Size of the list : : 0
curently : 300 over 300 created
Size of the list : : 0
curently : 400 over 400 created
Size of the list : : 0
curently : 500 over 500 created
Size of the list : : 0
curently : 600 over 600 created
Size of the list : : 0
curently : 700 over 700 created
Size of the list : : 0
curently : 800 over 800 created
Size of the list : : 0
curently : 900 over 900 created
Size of the list : : 0
curently : 1000 over 1000 created
Still 1000 instances in memory... waiting ...
Still 1000 instances in memory... waiting ...
Still 1000 instances in memory... waiting ...
Still 1000 instances in memory... waiting ...

正如我在 this question 的答案中读到的那样,不需要调用垃圾收集器,因此我显式调用 GC(3 条注释行)。现在几乎所有个体似乎都被解放了:

curently : 10000 over 10000 created
Still 7435 instances in memory... waiting ...
at the end : 0 over 10000 created

有时,1 或 2 个实例似乎保留在内存中......

但是如果我尝试使用更多对象(java TestCounter 10 100000),结果会令人惊讶。 “实例数”可以为负数,这表明 finalize() 方法被调用了两次...

Size of the list : : 0
curently : 896577 over 1000000 created
Still 892834 instances in memory... waiting ...
Still -762 instances in memory... waiting ...
Still -762 instances in memory... waiting ...
Still -762 instances in memory... waiting ... 

您能解释一下这种行为吗?

也许我犯了一个错误或误解了某些东西......

public class Counter{

    static long number = 0;
    static long totalNumber = 0;


    public Counter(){
        number++; 
        totalNumber++;

    }

    public static long getNumber(){
        return number;
    }

    public static long getNombreTotal(){
        return totalNumber;
    }

    protected void finalize() throws Throwable{
            try {       
                number--;
            } finally {
                super.finalize();
            }
    }

}

import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

public class TestCompteur{

    public static void methode(int iteration, int taille){

        for (int j=0; j<iteration; j++){

            ArrayList<Counter> liste = new ArrayList<Counter>();

            for (int i=0; i<taille; i++){
                liste.add(new Counter());
            }

            liste.clear();

            System.out.println("Size of the list : : "+liste.size());           
            System.out.println("curently : " + Counter.getNumber() + " over " + Counter.getNombreTotal() +" created");      
        }   



    }

    public static void main(String[] args){


        methode(Integer.decode(args[0]), Integer.decode(args[1]));

        /*
        System.gc();
        System.runFinalization();
        System.gc();
        */

        while (Counter.getNumber() != 0){
            //System.out.print(".");
            System.out.println("Still " + Counter.getNumber() + " instances in memory... waiting ...");

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(TestCompteur.class.getName()).log(Level.SEVERE, null, ex);
                    }
        }
        System.out.println("at the end : " + Counter.getNumber() + " over " + Counter.getNombreTotal() +" created");
    }

}

最佳答案

我尝试了你的代码。虽然我没有像你一样得到负数number,但我陷入了困境:

curently : 923367 over 1000000 created
Still 1041 instances in memory... waiting ...
Still 1041 instances in memory... waiting ...
Still 1041 instances in memory... waiting ...

然后我同步了number的增量/减量:

public Counter()
{
    incNumber();
    totalNumber++;
}

public static synchronized void incNumber ()
{
    number++;
}

public static synchronized void decNumber ()
{
    number--;
}

protected void finalize() throws Throwable
{
    try {
        decNumber ();
    } finally {
        super.finalize();
    }
}

结果,number 达到 0,程序终止。

curently : 936759 over 1000000 created
at the end : 0 over 1000000 created

结论:

finalize() 不会对同一个对象调用两次,但是当多个线程(主线程和 GC 线程)在不同步的情况下修改同一个变量时,可能会发生奇怪的事情。

关于java - 多次调用finalize,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27014430/

相关文章:

Java Finalize 方法不调用

java - 如何在开区间 (x, y) 上获得下一个随机 double 值

java - 未知的顶级运算符(operator) : $limit

javascript - js中树对象实现的内存管理

Kotlin super.finalize()

java - 在 Java9 中,终结器已被弃用,取而代之的是引入了清理器。两者有什么区别?

java - 为什么java中静态需要连接<T>?

Java - 生成复杂的excel报告

memory-management - 释放 Java 堆空间

c++ - Visual C++ GC 接口(interface)如何启用它以及要包含哪个库