none
使用.net memory profiler 检查内存状态以及.net内存管理的若干问题 RRS feed

  • 问题

  • 最近使用了.net memory profiler研究了一下关于.net内存泄露问题(如果对.net的内存由托管堆管理而不会发生泄露有异议的可以google一下),有些疑问,希望和使用过该工具的xdjm或者.net大虾们做下交流。

    通过对同一业务流程的两次内存快照做对比,会发现很多第二次相对于第一次的Live instance和Disposed instance差异。

         根据该工具的用户手册,正常情况下两次对照的Disposed instance应该为零或者趋近于零,如果不为零,有两种情况是被允许的(短期对象和池),其他的应该很可能是内存泄露。由于似乎不能贴图,我就只能干说了。对于“new or removed intances”结果,在type页,左二列会有很多红色和黄色的惊叹号,说明有对象被disposed了但并没有别GC掉。找个红色惊叹号的点进去,进入到type detail页,标记了第二次相对于第一次快照某些该类型的对象被新创建了然后又被diposed掉或者只是新创建了或者只是被diposed掉。再点进去,就是该类型实例的details,一般都是和handler相关的。

    问题一:我想知道这些第二次快照相对于第一次被新创建又被diposed掉或者只是新创建的或者只是被disposed掉的是怎么发生的?因为是同一个业务流程,其内存中对象应该大体一致,什么样的情况会发生第二次快照相对第一次新创建对象然后又dispose掉?什么情况会发生只创建不dispose掉?什么情况会发生不创建只dispose?

    问题二:对于一个event handler订阅一个对象的方法,如果这个handler是静态的,这个订阅关系就一直存在,即使这个对象不再使用也不会被回收(之后有weakref来搞定这种泄露)。但.net得GC是在root ref开始遍历对象引用,如果是reachable的对象,就是不应该被回收的,对于unreachable的,就是需要被回收的,调用dispose方法(如果实现了finalize,再把这个对象放到另一个链表,调用finalize方法)。一次GC之后,reachable对象由于没有被回收,age增加1。但问题是,对于被静态handler订阅的对象,从root ref是可以直接到达的对象(静态handler就是root ref其中一个),为什么会被调用dispose方法?怎么会有调用dispose方法而没有被GC的情况发生?(因为但凡被移到回收队列需要被调用dispose方法的对象都是unreachable的对象)

    问题三:按照我的理解,两次相同的业务流程,两次内存快照理论上应该相同,为什么如果dispose的对象数(type页)不为零就是内存泄露?为什么不是live实例数(type页)不为零时是内存泄露?

    多谢!如果上面有理解不对的地方请大家不吝赐教!

    supertruman
    2009年10月23日 1:55

全部回复