我试着编写一个用于计算内存中实例数的类。我使用了一个静态属性 - 我在构造函数上递增它并在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");
}
}
答案 0 :(得分:1)
我尝试了你的代码。虽然我没有像你那样得到负面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线程)在没有同步的情况下修改同一个变量时,就会发生奇怪的事情。