为什么我们在heap上看到的exception object在stack上却找不到?

不用windbg解决High CPU的一个案例中,列举了exception过多而导致high cpu的情况,但是在后期用windbg分析dump的时候,遇到了一个问题:我看到了很多exceptions,但是就是不能!gcroot。猜想了一下原因,看了tom的blog,证实了我的分析。(这家伙是我遇到回邮件最准时的,如果有问题mail请教他,每天早上8点开机不一会必定有他的answer)

举例:用!dumpheap -stat命令,我们可以看到heap上有exception,这个System.Threading.TreadAbortException就是我要找到的元凶。

那么继续,GC里有个root的概念,简单来说就是如果一个对象被rooted了,那就意味着这个对象存在一个引用(直接或间接的被引用),这个root object有可能是这样几种形态:

  • stack上的作为参数(parameter)或局部变量(local)
  • 静态变量
  • 存在与Finalizer Queue中

我们看callstack上的信息,用!gcroot命令:

0:066> !gcroot 11c11a44
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 18 OSThread be4
Scan Thread 24 OSThread 2e0
Scan Thread 25 OSThread 358
Scan Thread 26 OSThread fc
Scan Thread 27 OSThread 5c4
Scan Thread 28 OSThread c84
Scan Thread 13 OSThread dd4
Scan Thread 15 OSThread b80
Scan Thread 17 OSThread d84
Scan Thread 16 OSThread 724
Scan Thread 8 OSThread 624
Scan Thread 7 OSThread ef4
Scan Thread 6 OSThread db0
Scan Thread 9 OSThread 5e4
Scan Thread 29 OSThread 6b0
Scan Thread 30 OSThread 8b4
Scan Thread 31 OSThread 260
Scan Thread 32 OSThread 1a4
Scan Thread 33 OSThread 420
Scan Thread 34 OSThread 900
Scan Thread 35 OSThread ef8
Scan Thread 36 OSThread eb0
Scan Thread 37 OSThread f90
Scan Thread 38 OSThread f8c
Scan Thread 39 OSThread df0
Scan Thread 40 OSThread de0
Scan Thread 41 OSThread bc0
Scan Thread 42 OSThread 710
Scan Thread 43 OSThread 87c
Scan Thread 44 OSThread 5c8
Scan Thread 45 OSThread 638
Scan Thread 46 OSThread 550
Scan Thread 47 OSThread 73c
Scan Thread 48 OSThread e4
Scan Thread 49 OSThread ba4
.......
.......

至此可以看出这个对象不是在全局(global)上的thread或者是referenced,我们之所以能在heap上看到,是因为这个对象在一个thread上,但是这个thread已经成功执行完成了,并且GC还没有清理(clean up)这个对象。所以这个对象仍然保留在托管堆(managed heap)直到GC进行下一次回收。GC是分代(generation)的,所以如果GC对存在于这个exception对象的代(generation)进行清理,那么他就被从堆(heap)上移除了。

posted @ 2008-04-22 10:14  new 维生素C.net()  阅读(1789)  评论(4编辑  收藏  举报