Thinking in Java 已经说的很清楚了. 垃圾回收器是自己来决定什么时候来回收垃圾的, 什么时候调用 finalize()方法也是不确定的. 不同的 JDK 版本的Java 虚拟机运行同一个这样的程序也会有不同的结果. 在我的机器上 JDK 1.4.1 b26, 结果是在创建2462个Chair对象后, i 就等于47了. 但是在你的机器上, i可能要等很才可能增加到47, 接果也会不同. 这其中还牵扯到多线程, 1 System.out.println("Beginning to finalize after"+ created+ "Chairs have been created");2 System.out.println("Finalizing Chair#47,"+created+"Chair have been created"); 这两条语句中输出的 created 是不一样的. 因为垃圾回收器和你的程序是在两个不同的线程运行的, 当第一个语句被打印后, 你的 主程序可能(注意是可能)会继续创建其它Chair对象, 当JVM觉得现在应该继续垃圾回收器的 线程时候, 第二条语句才会被输出. 而且你程序中有错误(可能是你输入错误),我给你纠正了. 顺便问一下, 我估计你是在用第二版本的 Thinking in java //Demonstration of the garbage //collector and finaliztion class Chair{ static boolean gcrun=false; static boolean f=false; static int created=0; static int finalized=0; int i; Chair(){ i=++created; if (created==47) System.out.println("Created 47"); } public void finalize(){ if(!gcrun){ //The first time finalize()is called: gcrun=true; System.out.println("Beginning to finalize after"+ created+ "Chairs have been created"); }
if(i==47){ System.out.println("Finalizing Chair#47,"+created+"Chair have been created"); f=true; } finalized++; } }public class Garbage { public static void main(String args[]) { while(!Chair.f) { new Chair(); new String(); } } }
class Chair{ static boolean gcrun=false; static boolean f=false; static int created=0; static int finalized=0; int i; Chair(){ i=++created; if (created==47) System.out.println("Created 47"); } public void finalize(){ if(!gcrun){ //The first time finalize()is called: gcrun=true; System.out.println("Beginning to finalize after"+created+"Chairs have been created"); } //如果我这里使用i,也就是书中的。会出现死循环。而当我使用finalized是很正常。 if(i==47) { System.out.println("Finalizing Chair#47,"+created+"Chair have been created"); f=true; } finalized++;} } public class Garbage { public static void main(String args[]) { while(!Chair.f){ new Chair(); new String(); } } }
C:\j>java Garbage Created 47 Beginning to finalize after3538Chairs have been created Finalizing Chair#47,3538Chair have been created
to caiyanying732 (caiyanying732) :AndrewCSDN()说得不是很明确,有些也说得不对!解答有几点:第一: caiyanying732 (caiyanying732) 你贴上的代码中有错误:
a:类Chair的{}少了一个 b:System.out.println("Finalizing Chair#47,"+"created+"Chair have been created");这句多了个双引号. 正确的应该是 System.out.println("Finalizing Chair#47,"+created+"Chair have been created"); 第二: 如AndrewCSDN()所说,垃圾回收器是自己来决定什么时候来回收垃圾的,而垃圾收集是一个独立的低优先级的线程,你可以调用实例的gc()方法来激活垃圾收集.然而,你不能预言,或者说保证垃圾收集会立即开始. 你可以运行垃圾收集器的方法,但不能保证垃圾收集会立即发生. 也可以在运行时用java -noasyncgc来关掉应用程序中的垃圾收集器 但如果我们关掉垃圾收集,几乎可以肯定程序会由于内存用尽而失败.第三: 如 AndrewCSDN()所说"不同的 JDK 版本的Java 虚拟机运行同一个这样的程序也会有不同的结果",在我的机器上结果是2788个对象. 但不是AndrewCSDN()所说那样"在创建2462个Chair对象后,i就等于47了" 正确的是(以我的机器为实例,因为我运行过上百遍,结果一样都是创建2788个Chair对象) :当机器创建2788个对象时,虚拟机开始调用垃圾收集,从而调用创建的第一个Chair的finalize()方法,显示"Beginning to finalize after 2788Chairs have been created"这一句,但第一个析构方法的i是1,不会运行 if(i==47) { System.out.println("Finalizing Chair#47, "+created+"Chair have been created"); f=true; } 里面的东西,当收集器进行到第47个对象时,i=47,就运行了if(i==47)判断语句里面的东西了.从而显示:"Finalizing Chair#47, 2788Chair have been created"这一句. 第四: 因为收集器是作为独立的线程进行的,所以在我机器上(JDK1.4.0_02)是分配CPU的时间片给垃圾收集器.所以从第1个Chair对象到第47个Chair对象一直运行垃圾收集,没有再做 while(!Chair.f) { new Chair(); new String(); } 的判断运行,所以直到第47个Chair对象时f已经是true了.再由CPU分时间片给主线程做while判断时,因为条件已经变成了假,所以跳出while()循环.程序结束!这个程序不会死循环的,检查一下你的程序,有没有我说的错误,和运行时候等等,因为不同版的虚拟机会不会执行垃圾收集器! 还有什么不明白,尽管说出来!我有什么不对地方也请指出!!祝好!
多谢你们能回答我的问题,还帮我指出毛病。但还有一点不明白的: to lionlxz 当机器创建2788个对象时,虚拟机开始调用垃圾收集,从而调用创建的第一个Chair的finalize()方法,显示"Beginning to finalize after 2788Chairs have been created"这一句,但第一个析构方法的i是1,不会运行 //这里为什么是i=1,i的值不是等于created的吗?
什么时候调用 finalize()方法也是不确定的. 不同的 JDK 版本的Java 虚拟机运行同一个这样的程序也会有不同的结果. 在我的机器上 JDK 1.4.1 b26, 结果是在创建2462个Chair对象后, i 就等于47了. 但是在你的机器上, i可能要等很才可能增加到47, 接果也会不同. 这其中还牵扯到多线程,
1 System.out.println("Beginning to finalize after"+ created+ "Chairs have been created");2 System.out.println("Finalizing Chair#47,"+created+"Chair have been created");
这两条语句中输出的 created 是不一样的.
因为垃圾回收器和你的程序是在两个不同的线程运行的, 当第一个语句被打印后, 你的
主程序可能(注意是可能)会继续创建其它Chair对象, 当JVM觉得现在应该继续垃圾回收器的
线程时候, 第二条语句才会被输出.
而且你程序中有错误(可能是你输入错误),我给你纠正了. 顺便问一下, 我估计你是在用第二版本的 Thinking in java
//Demonstration of the garbage
//collector and finaliztion
class Chair{
static boolean gcrun=false;
static boolean f=false;
static int created=0;
static int finalized=0;
int i;
Chair(){
i=++created;
if (created==47)
System.out.println("Created 47");
} public void finalize(){
if(!gcrun){
//The first time finalize()is called:
gcrun=true;
System.out.println("Beginning to finalize after"+ created+ "Chairs have been created");
}
if(i==47){
System.out.println("Finalizing Chair#47,"+created+"Chair have been created");
f=true;
}
finalized++;
}
}public class Garbage
{
public static void main(String args[])
{
while(!Chair.f)
{
new Chair();
new String();
}
}
}
应该是在我的机器上创建了2462个 Chair对象后, 垃圾回收器决定应该对第47个Chair对象回收, 这时候第47个Chair的finalize()方法被调用. 注意只有这个对象中的i等于47, 因为i是instance field. 所有创建的Chair对象中的 created是相等的,因为 created 是静态变量.
static boolean gcrun=false;
static boolean f=false;
static int created=0;
static int finalized=0;
int i;
Chair(){
i=++created;
if (created==47)
System.out.println("Created 47");
} public void finalize(){
if(!gcrun){
//The first time finalize()is called:
gcrun=true;
System.out.println("Beginning to finalize after"+created+"Chairs have been created");
}
//如果我这里使用i,也就是书中的。会出现死循环。而当我使用finalized是很正常。
if(i==47)
{
System.out.println("Finalizing Chair#47,"+created+"Chair have been created");
f=true;
}
finalized++;}
}
public class Garbage
{
public static void main(String args[])
{
while(!Chair.f){
new Chair();
new String();
}
}
}
Created 47
Beginning to finalize after3538Chairs have been created
Finalizing Chair#47,3538Chair have been created
caiyanying732 (caiyanying732) 你贴上的代码中有错误:
a:类Chair的{}少了一个
b:System.out.println("Finalizing Chair#47,"+"created+"Chair have been created");这句多了个双引号.
正确的应该是 System.out.println("Finalizing Chair#47,"+created+"Chair have been created");
第二:
如AndrewCSDN()所说,垃圾回收器是自己来决定什么时候来回收垃圾的,而垃圾收集是一个独立的低优先级的线程,你可以调用实例的gc()方法来激活垃圾收集.然而,你不能预言,或者说保证垃圾收集会立即开始. 你可以运行垃圾收集器的方法,但不能保证垃圾收集会立即发生. 也可以在运行时用java -noasyncgc来关掉应用程序中的垃圾收集器
但如果我们关掉垃圾收集,几乎可以肯定程序会由于内存用尽而失败.第三:
如 AndrewCSDN()所说"不同的 JDK 版本的Java 虚拟机运行同一个这样的程序也会有不同的结果",在我的机器上结果是2788个对象.
但不是AndrewCSDN()所说那样"在创建2462个Chair对象后,i就等于47了" 正确的是(以我的机器为实例,因为我运行过上百遍,结果一样都是创建2788个Chair对象)
:当机器创建2788个对象时,虚拟机开始调用垃圾收集,从而调用创建的第一个Chair的finalize()方法,显示"Beginning to finalize after 2788Chairs have been created"这一句,但第一个析构方法的i是1,不会运行
if(i==47)
{
System.out.println("Finalizing Chair#47, "+created+"Chair have been created");
f=true;
} 里面的东西,当收集器进行到第47个对象时,i=47,就运行了if(i==47)判断语句里面的东西了.从而显示:"Finalizing Chair#47, 2788Chair have been created"这一句.
第四: 因为收集器是作为独立的线程进行的,所以在我机器上(JDK1.4.0_02)是分配CPU的时间片给垃圾收集器.所以从第1个Chair对象到第47个Chair对象一直运行垃圾收集,没有再做
while(!Chair.f)
{ new Chair();
new String();
}
的判断运行,所以直到第47个Chair对象时f已经是true了.再由CPU分时间片给主线程做while判断时,因为条件已经变成了假,所以跳出while()循环.程序结束!这个程序不会死循环的,检查一下你的程序,有没有我说的错误,和运行时候等等,因为不同版的虚拟机会不会执行垃圾收集器!
还有什么不明白,尽管说出来!我有什么不对地方也请指出!!祝好!
to lionlxz
当机器创建2788个对象时,虚拟机开始调用垃圾收集,从而调用创建的第一个Chair的finalize()方法,显示"Beginning to finalize after 2788Chairs have been created"这一句,但第一个析构方法的i是1,不会运行 //这里为什么是i=1,i的值不是等于created的吗?
"//这里为什么是i=1,i的值不是等于created的吗"
你创建了2788个Chair对象后, 每个Chiar对象里的i都是不同的(从0到2787),因为i是instance field. 而created 是 static variable静态变量,所有的Chiar对象最后都有一个相等的created 值 2787, (但是运行过程中created 的值是递增的,所以i才会有不同的值)