6.消除过期的对象引用

内存泄露常见来源:

一、过期引用

元素出栈,忘记设置为Null:

6.消除过期的对象引用_第1张图片

如果一个栈先是增长,然后再收缩,从栈中弹出来的对象不会被当作垃圾回收,即使使用栈的程序不再引用这些对象,它们也不会被回收。因为栈内部维护着对这些对象的过期引用(obsolete reference)。指永远也不会再被解除的引用

在本例中,在elements数组的“活动部分(active portion)”之外的任何引用都是过期的。活动部分指elements中下标小于size的那些元素。

解决方法清空引用。元素被弹出栈指向它的引用就过期了。修改如下:

6.消除过期的对象引用_第2张图片

清空好处:如果它们以后又被错误地解除引用,程序抛出NullPointerException异常

最好的方法:让包含该引用的变量结束其生命周期。如果在最紧凑的作用域范围内定义每一个变量(见第45条),这种情形会自然而然地发生。

只要类是自己管理内存,程序员就应该警惕内存泄漏问题。一旦元素被释放掉,该元素中包含的任何对象引用都应该被清空。

二、缓存。

只要在缓存之外存在对某个项的键的引用(外部代码没有持有m中的一个键的引用),该项就有意义;如果没有,可以使用WeakHashMap来代表缓存。过期则清空

6.消除过期的对象引用_第3张图片

三、监听器和其他回调。

6.消除过期的对象引用_第4张图片

AppCompatActivity实现一个接口OnNetworkChangedListener,用来监听网络的变化。然后,把这个监听器注册NetworkManager实例中。

NetworkManager实例持有监听器(MainActivity是实现者,指向MainActivity对象的引用)。

当NetworkManger实例的生命周期比MainActivity长,当MainActivity销毁时(比如屏幕发生旋转),NetworkManager实例还没有销毁,它持有指向MainActivity对象的引用。系统回调MainActivity的onDestroy方法,这时,GC是要回收MainActivity对象的,但是,MainActivity对象依然可达(NetworkManager实例持有指向MainActivity对象的引用),所以没有回收,MainActivity对象泄露

解决办法:

6.消除过期的对象引用_第5张图片

https://www.cnblogs.com/WJQ2017/p/7634330.html

https://www.cnblogs.com/ttylinux/archive/2017/03/12/6536929.html

你可能感兴趣的:(6.消除过期的对象引用)