Android内存优化五:Android垃圾回收器机制
2016-03-03 08:49
375 查看
GC是垃圾收集的意思(GabageCollection)。和JAVA一样,ANDROID系统也是由GC来自动回收内存的。android中一个应用的启动,android系统都会为这个应用分配一个dalivk虚拟机,以便这个应用运行在这个独立的虚拟机上,可是一个虚拟机内存大小一般也是限制的(20M左右)。可见,一个应用的运行所申请的内存不可能无限大的。
通常,GC是在一个单独的比较低优先 级线程中运行。这样其内存的释放就交给了GC来处理,GC会实时监测并释放“无效”的内存。这里关键字“无效”就引起了我们的注意,什么内存单元是无效的呢?一般GC采用的办法是引用计数法来判断一个内存单元(一个变量)是否是无效的内存,其实很多系统都采用了这种办法,比如Cocos2D这个游戏开发的引擎也采用了这种引用计数法。引用计数法简单的说就是指一个变量或是一块内存当前被引用的次数,如果引用的次数等于0,则可以表示这个变量或是这块内存没有被引用了,那么GC“很可能”就会去释放他了。这里要提一下:“很可能”呢?我觉得这是最贴近实时的,首先GC运行在一个优先级较低的线程;其次GC回收的具体工作也是相当复杂的(这里要注意:引用计数法只是GC中的一个常用的方法,GC对内存管理的方法都很复杂,比如还会用到年代方法等,自己可以去研究研究),比如同时需要释放大量内存时候,并且CPU资源有相对很紧张,GC可能就会选择性的释放一些内存资源。那我们做android开发时候,就需要特别注意内存的引用,比如一个占用内存大的对象、以及一个bitmap对象,他们往往无用、又占用大量内存资源而GC又没有办法去释放,从而造成严重后果。一般的原则是:对占用大量内存的变量,使用完后主动将其置为NULL,可能的话主动调用一次GC:system.gc(),特别是一些static型的引用风险很大。
明白了GC以及引用计数法,下面来说一下几种引用:
强引用 SrongReference:
一般我们常用到的引用就是强引用,比如上面提到的引用计数法里面的引用。
软引用 SoftReference:
对于GC来说, SoftReference的强度明显低于 SrongReference。SoftReference修饰的引用,其告诉GC:我是一个 软引用,当内存不足的时候,我指向的这个内存是可以给你释放掉的。我们来看一下android系统中的一个使用实列(MessageItem.java):
一般对于这种占用内存资源比较大的,又不是必要的变量;或者一些占用大量内存资源的一些缓存的变量,就需要考虑 SoftReference。
弱引用WeakReference:
对于GC来说, WeakReference 的强度又明显低于 SoftReference 。WeakReference 修饰的引用,其告诉GC:我是一个弱 引用,对于你的要求我没有话说,我指向的这个内存是可以给你释放掉的。我们来看一下android系统中的一个使用实列(InstalledAppDetails.java 这是一段停用一个APP的代码段,其中这个需要停用APP的InstalledAppDetails对象 在这里的引用就采用了弱引用 ):
虚引用 PhantomReference:
虚引用其实和上面讲到的各种引用不是一回事的,他主要是为跟踪一个对象何时被GC回收。在android里面也是有用到的:FileCleaner.java
http://blog.csdn.net/huanglong1987/article/details/20621951
通常,GC是在一个单独的比较低优先 级线程中运行。这样其内存的释放就交给了GC来处理,GC会实时监测并释放“无效”的内存。这里关键字“无效”就引起了我们的注意,什么内存单元是无效的呢?一般GC采用的办法是引用计数法来判断一个内存单元(一个变量)是否是无效的内存,其实很多系统都采用了这种办法,比如Cocos2D这个游戏开发的引擎也采用了这种引用计数法。引用计数法简单的说就是指一个变量或是一块内存当前被引用的次数,如果引用的次数等于0,则可以表示这个变量或是这块内存没有被引用了,那么GC“很可能”就会去释放他了。这里要提一下:“很可能”呢?我觉得这是最贴近实时的,首先GC运行在一个优先级较低的线程;其次GC回收的具体工作也是相当复杂的(这里要注意:引用计数法只是GC中的一个常用的方法,GC对内存管理的方法都很复杂,比如还会用到年代方法等,自己可以去研究研究),比如同时需要释放大量内存时候,并且CPU资源有相对很紧张,GC可能就会选择性的释放一些内存资源。那我们做android开发时候,就需要特别注意内存的引用,比如一个占用内存大的对象、以及一个bitmap对象,他们往往无用、又占用大量内存资源而GC又没有办法去释放,从而造成严重后果。一般的原则是:对占用大量内存的变量,使用完后主动将其置为NULL,可能的话主动调用一次GC:system.gc(),特别是一些static型的引用风险很大。
明白了GC以及引用计数法,下面来说一下几种引用:
强引用 SrongReference:
一般我们常用到的引用就是强引用,比如上面提到的引用计数法里面的引用。
软引用 SoftReference:
对于GC来说, SoftReference的强度明显低于 SrongReference。SoftReference修饰的引用,其告诉GC:我是一个 软引用,当内存不足的时候,我指向的这个内存是可以给你释放掉的。我们来看一下android系统中的一个使用实列(MessageItem.java):
private SoftReference<Bitmap> mBitmapCache = new SoftReference<Bitmap>(null); public Bitmap getIpMessageBitmap() { return mBitmapCache.get(); } public void setIpMessageBitmapCache(Bitmap bitmap) { if (null != bitmap) { mBitmapCache = new SoftReference<Bitmap>(bitmap); } }
一般对于这种占用内存资源比较大的,又不是必要的变量;或者一些占用大量内存资源的一些缓存的变量,就需要考虑 SoftReference。
弱引用WeakReference:
对于GC来说, WeakReference 的强度又明显低于 SoftReference 。WeakReference 修饰的引用,其告诉GC:我是一个弱 引用,对于你的要求我没有话说,我指向的这个内存是可以给你释放掉的。我们来看一下android系统中的一个使用实列(InstalledAppDetails.java 这是一段停用一个APP的代码段,其中这个需要停用APP的InstalledAppDetails对象 在这里的引用就采用了弱引用 ):
static class DisableChanger extends AsyncTask<Object, Object, Object> { final PackageManager mPm; final WeakReference<InstalledAppDetails> mActivity; final ApplicationInfo mInfo; final int mState; DisableChanger(InstalledAppDetails activity, ApplicationInfo info, int state) { mPm = activity.mPm; mActivity = new WeakReference<InstalledAppDetails>(activity); mInfo = info; mState = state; } }
虚引用 PhantomReference:
虚引用其实和上面讲到的各种引用不是一回事的,他主要是为跟踪一个对象何时被GC回收。在android里面也是有用到的:FileCleaner.java
http://blog.csdn.net/huanglong1987/article/details/20621951
相关文章推荐
- Android内存优化四:从代码角度进行优化
- Android内存优化三:对Bitmap的内存优化
- Android内存优化二:使用软引用和弱引用
- Android Studio首次运行卡在Fetching android SDK compoment information
- 2014 android毕设代做 代做Android毕设 安卓毕设
- android开发步步为营之65:解决ScrollView和ListView触摸事件onInterceptTouchEvent相互冲突问题
- 2015最流行的Android组件、工具、框架大全
- 一对多 pc上运行android客户端
- Android开发者编码风格
- 错误记录:Resource ID #0x7f040006 type #0x12 is not valid
- 个人进阶之路——安卓蓝牙模块(4)
- Android布局管理器总结一:LinearLayout
- 小刚的Android研究笔记~在未开启USB调试的Android手机绕过锁屏密码
- Android事务理解和Fragment的执行事务
- iMindMap Android中字体格式该怎么进行修改
- 第三方知乎专栏应用Android源码
- Kotlin 开发Android
- Android ADB server didn't ACK * failed to start d
- void android.os.Bundle.putBoolean(java.lang.String
- Android5.0 短信拦截技术分析