Open zgq105 opened 10 months ago
内存泄漏的本质是长生命周期的对象持有短生命周期对象的引用,导致本应该被回收的短生命周期对象不能被GC回收导致内存泄漏。
class BActivity : AppCompatActivity() { inner class MyHandler : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { super.handleMessage(msg) Log.d("zgq", "handleMessage:${msg.what}") } } private val myHandler = MyHandler() override fun onResume() { super.onResume() //模拟handler内存泄漏,启动页面然后马上关闭页面 myHandler.sendEmptyMessageDelayed(1103, 20 * 1000) } }
从上面这里实例代码我们知道可以通过Profiler或者leakcanary都会发现内存泄漏了,通过阅读源码可以知道以下的引用链:
ActivityThread中主线程 -> ThreadLocalMap -> ThreadLocal -> Looper -> MessageQueue -> Message -> Handler -> Activity
因为主线程是一直存在的,导致引用链不能被回收,进而导致Activity 实例发生内存泄漏的根本原因。GC Root引用链已经列出来了,重点查看以上相关的源码还是很好理解的。所以这里的GC Root主线程对象。
class BActivity : AppCompatActivity() { inner class MyHandler : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { super.handleMessage(msg) Log.d("zgq", "handleMessage:${msg.what}") } } private val myHandler = MyHandler() override fun onResume() { super.onResume() //模拟子线程内存泄漏,启动页面然后马上关闭页面 Thread { Thread.sleep(20 * 1000) myHandler.sendEmptyMessage(11) Log.d("zgq", "thread:end") }.start() } }
按相同的方式分析以上代码的引用链是:子线程 -> Handler -> Activity ,因为这里是子线程对象引用了Handler对象 ,而Handler 对象又引用了Activity对象,导致内存泄漏;这里的GC Root就是子线程的实例对象。
1. 内存泄漏的原因?
内存泄漏的本质是长生命周期的对象持有短生命周期对象的引用,导致本应该被回收的短生命周期对象不能被GC回收导致内存泄漏。
2. Hander内存泄漏分析?
从上面这里实例代码我们知道可以通过Profiler或者leakcanary都会发现内存泄漏了,通过阅读源码可以知道以下的引用链:
ActivityThread中主线程 -> ThreadLocalMap -> ThreadLocal -> Looper -> MessageQueue -> Message -> Handler -> Activity
因为主线程是一直存在的,导致引用链不能被回收,进而导致Activity 实例发生内存泄漏的根本原因。GC Root引用链已经列出来了,重点查看以上相关的源码还是很好理解的。所以这里的GC Root主线程对象。
3.线程内存泄漏分析?
按相同的方式分析以上代码的引用链是:子线程 -> Handler -> Activity ,因为这里是子线程对象引用了Handler对象 ,而Handler 对象又引用了Activity对象,导致内存泄漏;这里的GC Root就是子线程的实例对象。