mono中的内存泄漏和WeakReference(弱引用)的使用
来源:互联网 发布:java统计报表怎么做 编辑:程序博客网 时间:2024/05/18 05:18
我们大家有时候在做 unity 项目的时候,游戏后期最常见的问题,应该就是内存泄漏了。
其实这里面有一些小细节,就可能在你不知不觉间导致内存泄漏的发生。
这里说说释放对象时容易发生的问题。
先来看一段代码:
private float m_countdown = 10; private bool m_turnOn = false; TestB m_tb; TestA m_ta; // Use this for initialization void Start() { m_turnOn = true; m_tb = new TestB(); m_ta = new TestA(m_tb); } // Update is called once per frame void Update() { if (m_turnOn == false) return; if (m_countdown >= 0) { m_countdown -= Time.deltaTime; } else { m_turnOn = false; m_ta = null; GC.Collect(); Debug.LogError("清理内存"); } } public class TestA { private long[] m_array; TestB m_tb; public TestA(TestB tb) { m_array = new long[100000000]; m_tb = tb; m_tb.TestFun(); } } public class TestB { private long[] m_array; public TestB() { m_array = new long[100000000]; } public void TestFun() { Debug.LogError("测试方法"); } }
代码内容十分的简单,我就不说了,我们来看用 Profiler 工具所截取的内存用量显示
gc前:
我们看到了,Mono内存是 2.99G (别问我mono内存是什么。。。)
gc后:
我们看到了,经过一次gc后,内存降到了 2.24G ,这时候,也许有人该说了,内存这不是降低了吗,没错呀╮(╯▽╰)╭。我要告诉你,少年,你高兴的太早了!
现在,我们再来看一段代码:
private float m_countdown = 10; private bool m_turnOn = false; WeakReference m_wrf_b; TestA m_ta; // Use this for initialization void Start() { m_turnOn = true; TestB tb = new TestB(); m_wrf_b = new WeakReference(tb); m_ta = new TestA(m_wrf_b); } // Update is called once per frame void Update() { if (m_turnOn == false) return; if (m_countdown >= 0) { m_countdown -= Time.deltaTime; } else { m_turnOn = false; m_ta = null; GC.Collect(); Debug.LogError("清理内存"); } } public class TestA { private long[] m_array; WeakReference m_wrf; public TestA(WeakReference wrf) { m_array = new long[100000000]; m_wrf = wrf; TestB tb = (TestB)m_wrf.Target; tb.TestFun(); } } public class TestB { private long[] m_array; public TestB() { m_array = new long[100000000]; } public void TestFun() { Debug.LogError("测试方法"); } }
现在,让我们再来做一遍之前的过程。
gc前:
gc后:
所以这一切是为什么呢?
主要原因就是因为我们new出来的这个对象,其实在c#中被称作强引用对象。
举例来说就是,在A对象依赖于B对象时,如果我们把B释放了,你会认为我们连A也一起释放了。
其实这只是你的错觉,真实情况是你释放了B,但是A是强引用类型,结果你的A找不到依赖了,变成内存泄漏了。。。解决这个问题有2种办法,一种就是:
你在释放B的同时,把A也一起干掉,像第一段代码的gc那里改成这样:
m_tb = null;m_ta = null;
或者用第2段代码里的方法:
正所谓有强就有弱,WeakReference
应该是c#从java那里学来的,叫做弱引用对象,原理我就不说了,你去查查就明白了。
WeakReference
就是专门用来解决因为这种依赖关系造成的gc释放问题。
当然WeakReference
也不是万能的,有时可能gc已经把对象释放了,但是你new出来的WeakReference
是不会释放的,结果你还用它去取存放在里面的对象,那时你取到的可能就是个null了。这时候,你就需要再重新把对象创建出来。
所以请结合你自己系统的底层架构,合理,正确的去使用弱引用对象。
题外话:
虽然这是一个我们写代码时,经常会范的错误,但是据说相同的问题,如果是在微软的.net
下,虽然可能会晚一些,但是泄漏的那块内存最终还是会被回收的,最新版本的mono
好像也行。(当然具体的我不清楚,也懒得去试了)
但是因为unity
的mono
版本太低了,记得官方说是 2.2 ,所以泄漏的内存就收不回来了,囧rz。
不过进行Scene的切换,会有助于释放一些我们无法管理的内存,这一点是可以充分利用起来的。所以还是希望
unity
能够把mono
版本给升一下,虽然这个希望十分的渺茫,残念~
- mono中的内存泄漏和WeakReference(弱引用)的使用
- mono中的内存泄漏和WeakReference(弱引用)的使用
- WeakReference 在android中的应用 弱引用防止内存泄漏
- java弱引用(WeakReference)和SoftReference的区别以及在android内存处理的作用
- java弱引用(WeakReference)和SoftReference的区别以及在android内存处理的作用
- java弱引用(WeakReference)和SoftReference的区别以及在android内存处理的作用
- java弱引用(WeakReference)和SoftReference的区别以及在android内存处理的作用
- java弱引用(WeakReference)和SoftReference的区别以及在android内存处理的作用
- java弱引用(WeakReference)和SoftReference的区别以及在android内存处理的作用
- java弱引用(WeakReference)和SoftReference的区别以及在android内存处理的作用
- java弱引用(WeakReference)和SoftReference的区别以及在android内存处理的作用
- android 使用WeakReference简单的检测内存泄漏
- JAVA中的强引用、软引用(SoftReference)、弱引用(WeakReference)和幽灵引用(PhantomReference)
- 内存优化:SoftReference 和 WeakReference 软引用与弱引用
- JAVA中的WeakReference(弱引用)
- C#中的弱引用(WeakReference)
- java弱引用(WeakReference)和SoftReference的区别
- Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
- Eclispse 更换主题Theme
- Codeforces 比赛代码记录及心得
- leetcode 350. Intersection of Two Arrays II
- 推送通知的跳转
- 百度首页(HTML5)
- mono中的内存泄漏和WeakReference(弱引用)的使用
- Andrid5.0新特性——SVG(可缩放矢量图)
- ubuntu 14.04 利用ap-hotspot建立wifi热点失效
- uva 524 - Prime Ring Problem
- codeforces 675-E Trains and Statistic 线段树+dp
- Centos中搭建python3开发环境
- 2. SpringMVC_HelloWorld
- 9.3顺序容器操作
- Codeforces Beta Round #2