内存泄露常见来源:
一、过期引用
元素出栈,忘记设置为Null:
如果一个栈先是增长,然后再收缩,从栈中弹出来的对象不会被当作垃圾回收,即使使用栈的程序不再引用这些对象,它们也不会被回收。因为栈内部维护着对这些对象的过期引用(obsolete reference)。指永远也不会再被解除的引用。
在本例中,在elements数组的“活动部分(active portion)”之外的任何引用都是过期的。活动部分指elements中下标小于size的那些元素。
解决方法:清空引用。元素被弹出栈,指向它的引用就过期了。修改如下:
清空好处:如果它们以后又被错误地解除引用,程序抛出NullPointerException异常
最好的方法:让包含该引用的变量结束其生命周期。如果在最紧凑的作用域范围内定义每一个变量(见第45条),这种情形会自然而然地发生。
只要类是自己管理内存,程序员就应该警惕内存泄漏问题。一旦元素被释放掉,该元素中包含的任何对象引用都应该被清空。
二、缓存。
只要在缓存之外存在对某个项的键的引用(外部代码没有持有m中的一个键的引用),该项就有意义;如果没有,可以使用WeakHashMap来代表缓存。过期则清空
三、监听器和其他回调。
AppCompatActivity实现一个接口OnNetworkChangedListener,用来监听网络的变化。然后,把这个监听器注册到NetworkManager实例中。
NetworkManager实例持有监听器(MainActivity是实现者,指向MainActivity对象的引用)。
当NetworkManger实例的生命周期比MainActivity长,当MainActivity销毁时(比如屏幕发生旋转),NetworkManager实例还没有销毁,它持有指向MainActivity对象的引用。系统回调MainActivity的onDestroy方法,这时,GC是要回收MainActivity对象的,但是,MainActivity对象依然可达(NetworkManager实例持有指向MainActivity对象的引用),所以没有回收,MainActivity对象泄露。
解决办法:
https://www.cnblogs.com/WJQ2017/p/7634330.html
https://www.cnblogs.com/ttylinux/archive/2017/03/12/6536929.html