1.什么事内存泄漏
内存不在GC的掌控之中了
本来应该回收的对象,还存留在内存中,
(1)什么是GC(垃圾回收机制)?
某对象不再有任何的任何的引用的时候才会进行回收,举例(餐厅餐具回收),
延伸:GC回收机制的原理,深入的话去了解JVM虚拟机
(GC ROOT TRACING回收算法)
GC动作发生的时候,从一个GCROOT对象开始往下走,找到一个对象是被GCROOT对象所持有,那么久不会回收,以此类推,只要持有就不会回收,找到没有被引用的对象,就会标记为允许被回收的,例外情况,就是内存泄露了.
①可以被GCROOT对象引用的点是哪些?
在JAVA STACK中引用的对象
在方法区中静态引用指向的对象
方法区中常量引用指向的对象
Native方法中JNI引用的对象
活着的Thread
②怎么判断一个对象是垃圾对象
垃圾对象就是没有被引用吗,no,没有被引用是可以回收的,这是一个主观判断,假设我们new了一个对象,然后退出了程序,去内存中查看,那这个对象也是垃圾对象,在GC眼里这不是垃圾对象,但是在我们眼里,这就是垃圾对象,
2.确定项目中存在内存泄漏
粗略判断AndroidMonitor--System Infomations---Activity.View等数量是否为0
3.确定内存泄漏在哪儿
(1)AndroidStudioMemoryMonitor工具
(2)粗略估计不行的话,可以生成hprof文件,用内存分析工具来分析,例如MAT,LeakCanary
4.常见的内存泄漏
内存泄漏产生的原因在Android中大致分为以下几种:原博客地址
(1).static变量引起的内存泄漏
因为static变量的生命周期是在类加载时开始 类卸载时结束,也就是说static变量是在程序进程死亡时才释放,如果在static变量中 引用了Activity 那么 这个Activity由于被引用,便会随static变量的生命周期一样,一直无法被释放,造成内存泄漏。
解决办法:
在Activity被静态变量引用时,使用 getApplicationContext 因为Application生命周期从程序开始到结束,和static变量的一样。
(2).线程造成的内存泄漏
类似于上述例子中的情况,线程执行时间很长,及时Activity跳出还会执行,因为线程或者Runnable是Acticvity内部类,因此握有Activity的实例(因为创建内部类必须依靠外部类),因此造成Activity无法释放。
AsyncTask 有线程池,问题更严重
解决办法:
1.合理安排线程执行的时间,控制线程在Activity结束前结束。
2.将内部类改为静态内部类,并使用弱引用WeakReference来保存Activity实例 因为弱引用 只要GC发现了 就会回收它 ,因此可尽快回收
(3).BitMap占用过多内存
bitmap的解析需要占用内存,但是内存只提供8M的空间给BitMap,如果图片过多,并且没有及时 recycle bitmap 那么就会造成内存溢出。
解决办法:
及时recycle 压缩图片之后加载图片
(4).资源未被及时关闭造成的内存泄漏
比如一些Cursor 没有及时close 会保存有Activity的引用,导致内存泄漏
解决办法:
在onDestory方法中及时 close即可
(5).Handler的使用造成的内存泄漏
由于在Handler的使用中,handler会发送message对象到 MessageQueue中 然后 Looper会轮询MessageQueue 然后取出Message执行,但是如果一个Message长时间没被取出执行,那么由于 Message中有 Handler的引用,而 Handler 一般来说也是内部类对象,Message引用 Handler ,Handler引用 Activity 这样 使得 Activity无法回收。
解决办法:
依旧使用 静态内部类+弱引用的方式 可解决
网友评论