垃圾回收时发生的一个诡异问题[Java编程]
本文“垃圾回收时发生的一个诡异问题[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
前些天在论坛里看到了一篇帖子垃圾汇集问题——是不是bug其问题以下:
static tc gto;
public class tc
{
public int a=99;
~tc()
{
a=-1; //set breakpoint 1
gto=this;
}
}
private void button1_Click(object sender,EventArgs e)
{
tc to=new tc();
GC.Collect();
GC.WaitForPendingFinalizers();
return; // set breakpoint 2
}
two problems:
click button once,it seem the ~tc() not execute at all.and it will excute at the second time clicking.why?
the second clicking,breakpoint 2, "gto" and "to", gto.a=-1,while to.a=99,why?
问题很好解答第一次强迫回收的时刻并不能回收部分变量to,只有下次点击的时刻才会回收上次产生的tc对象所以~tc()没有当即履行.而第二个问题是因为在析构函数中将对象的a置为-1并将引用赋值给了一个全局对象所以gto.a=-1,而新new出的来的tc对象a自然为99.我本来对第一个问题的解答信心满满,但当我正要答复问题时我看到了gomoku 的答复,他说到:
1,在调试时,Visual Studio供应了显示当即值的功效,比方让你的breakpoint 2的地方,可以查抄tc的值.
要查抄tc的值,这就要求tc不能被垃圾回收,为此Visual Studio调试器插入了特别代码以保证tc在脱离button1_Click()从前不会被回收.
2,Release版就差别了.你把例子用Release编译运行,就会发现,同Debug相反,~tc()在第一次GC.Collect时就被调用了.
我立即着手举行试验,发现release下公然如gomoku所说我不免对自己的理解有所猜疑.因为我坚信这必定和vs的断点无关,并且msdn,.net书籍,国内外技术文章在讲授垃圾回收原理时都是这么注释的”一开始gc把托管堆上的对象都视为可回收的,然后从利用程序的一组根动身探求可达对象,不可达的对象则被回收.由JIT编译器和CLR运行时保护根指针列表,主要包含全局变量、静态变量、部分变量和存放器指针等“所以我认为即便在release下也因该和debug下表现相同,除非release下有优化操作根本就不会保存这个部分变量.所以我即刻看debug和release两个版本的IL
debug:
IL_0000: nop
IL_0001: newobj tc::.ctor
IL_0006: stloc.0
IL_0007: call System.GC::Collect
IL_000c: nop
IL_000d: call System.GC::WaitForPendingFinalizers
IL_0012: nop
IL_0013: br.s IL_0015
IL_0015: ret
release:
ilAddr = 01394590
IL_0000: newobj tc::.ctor
IL_0005: pop
IL_0006: call System.GC::Collect
IL_000b: call System.GC::WaitForPendingFinalizers
IL_0010: ret
以上是“垃圾回收时发生的一个诡异问题[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |