zoukankan      html  css  js  c++  java
  • .net 循环引用是否会造成内存泄漏

    一直想做这么一个测试,人和手的测试。类型"人"有一个属性"手",需要"手"也可以读取"人"的数据。则"手"下面也有一个属性"人"。

    如果用代码表现,则是:

    public class Class人
    {
        private Class手 _手;
        public Class手 手 { get { return _手; } set { _手 = value; } }
    
        private Class脚 _脚;
        public Class脚 脚 { get { return _脚; } set { _脚 = value; } }
    
        private Class脑 _脑;
        public Class脑 脑 { get { return _脑; } set { _脑 = value; } }
    
        public Class人()
        {
            _手 = new Class手(this);
            _脚 = new Class脚(this);
            _脑 = new Class脑(this);
        }
    }
    
    public class Class手
    {
        private Class人 _人;
        public Class人 人 { get { return _人; } }
    
        public Class手(Class人 one)
        {
            _人 = one;
        }
    }

    这样可以实现 人.手 和 手.人 的相互访问。

    我的疑问是:人和手之间的这种相互强引用会不会造成资源一直处于被引用状态,不能被回收,从而导致内存泄漏?

    于是做了一个测试,测试的思路是:建立两个相互引用的类A/B,其中A含有B,B只需要访问A。A构造的时候会占用大量的内存。执行的时候,在函数以外定义变量C来承装List<A>并初始化。在函数内,重复的生成A的实例并放到C中。在某个时段,将C清空,强制垃圾回收,看A的集合占用的内存是否会释放。代码如下:

    public class Class人
    {
        private Class手 _手;
        public Class手 手 { get { return _手; } set { _手 = value; } }
    public List<string> Data;
        public Class人()
        {
            _手 = new Class手(this);
            Data = new List<string>();
            for (int i = 0; i < 1000; i++)
                Data.Add(Enumerable.Range(1, 30).Select(x => x.ToString()).Aggregate((x, y) => x + y));
        }
    }
    
    public class Class手
    {
        private Class人 _人;
        public Class人 人 { get { return _人; } }
    
        public Class手(Class人 one)
        {
            _人 = one;
        }
    }

    执行代码:

    static List<Class人> data = new List<Class人>();
    static void Main(string[] args)
    {
        for (int i = 0; i < 1000; i++)
            data.Add(new Class人());
    
        Console.WriteLine("ok");
        var read = Console.ReadLine();
        if (read == "Y")
        {
            data.Clear();
            GC.Collect();
        }
    
        Console.ReadKey();
    }

    测试的结果如下:

    1. 在启动程序前,内存占用61%;

    2. 启动后,"ok"前,也就是生成Class人的实例集合后,内存占用68%。

    3.1 如果此时输入"Y",立刻清空承载的data变量,并进行垃圾回收,内存占用返回至62%,关闭程序后返回61%。

    3.2  如果此时输入"Y",只是清空data,不执行垃圾回收,内存还停留在68%,关闭程序后直接返回61%(参考3.1,等到下一个垃圾回收时,应该会清空至62%)

    由此可以推出,即使数据里面,class人和class手相互引用了,但没有其他数据调用时,垃圾回收机制仍然会将其视为垃圾然后回收。

    本来想通过弱引用处理这种相互引用的,通过测试后,感觉不用。以下贴出我查询到的一些声音:

    ".NET不是使用引用计数器的方法"

    ".NET处理循环引用不是通过弱引用来实现的,而是通过遍历对象,释放无法访问的对象来完成的"

    由于对.net的垃圾回收机制研究得不通透,所以给不了一些原理上的解释,如果有大牛知道这一部分,欢迎给我留言。

    如果测试结果有误,请严肃纠正。

    转载请注明出处:http://www.cnblogs.com/icyJ

  • 相关阅读:
    点击对应不同name的button,显示不同name的弹窗(弹窗功能)
    点击添加本地图片的前端效果制作
    巧用margin/padding的百分比值实现高度自适应(多用于占位,避免闪烁)
    移动端取消touch高亮效果
    手机网站的几点注意
    图片自动切换+链接
    使用DOM的方法获取所有li元素,然后使用jQuery()构造函数把它封装为jQuery对象
    使用jQuery匹配文档中所有的li元素,返回一个jQuery对象,然后通过数组下标的方式读取jQuery集合中第1个DOM元素,此时返回的是DOM对象,然后调用DOM属性innerHTML,读取该元素 包含的文本信息
    利用jQuery扩展接口为jQuery框架定义了两个自定义函数,然后调用这两个函数
    jQuery链式语法演示
  • 原文地址:https://www.cnblogs.com/icyJ/p/circularReference.html
Copyright © 2011-2022 走看看