WeakReference带来了什么

很多人说到:java存在内存泄漏

我不想反驳,因为我也开始慢慢说了,但我知道:内存泄漏,和,规范编码,是两个完全不同的概念
所以,我想说:请规范编码

java的“内存泄漏”:
堆内存不够用了
为什么不够用了?因为你认为已经过时的东西,没有被系统释放掉内存
为什么没有释放掉内存?
    因为你没有显示释放(c++版本)
    因为你还拥有着该对象的引用,而该对象没有被认为是垃圾(java版本)
        所以,你的编码并不规范
        
*********************************************************

WeakReference和内存泄漏有什么样的关系?
好像,没关系
那么WeakReference又是什么?

让我们先描述一个问题:
我有一个对象a(它非常的消耗内存,比如一个bitmap),当你同时申请了20个对象在android中,你将会看到out of memory异常
但是,如果你不缓存图片,那么用户将会认为你的app的性能非常差:
    当你的应用涉及到gridview,而每一个item都是一个图片时
一个矛盾:不加载图片(性能低下) vs 加载图片(加载多了,程序会挂)

一个解决:
只加载有限的图片,如5个图片
是的,这能解决问题
但是,你要为此付出的是什么:手动编写加载策略,以及,释放策略

WeakReference是什么:
先不看官方doc,让我们举个例子:
对象a非常的消耗内存,我有一个WeakReference对象(wra),并且和对象a关联:(wra & a are good friends)
那么,在虚拟机看来是什么样子呢:wra对象不是个垃圾,但是和wra对象相关联的对象(对象a)被认为是垃圾
是的,垃圾就是垃圾,但是:垃圾并不会立刻被清理
也就意味着:你仍然可以使用对象a,如果它还没被清理的情况下
如果对象a已经被清理呢:你必须重新构建对象a,再一次,和wra关联

那样做有什么样的好处:
你将可以肆无忌惮的申请任意多个“非常消耗内存”的对象(前提是,让他们和WeakReference关联)
使用这些对象前,先判定他们有没有被清理
    如果是,重新构建该对象(可能重新构建并不繁琐)
    如果不是,直接使用
总结:WeakReference负责了:释放策略

与WeakReference类似的还有:SoftReference,大同小异

*********************************************************

事实,并不是,看上去很美

我曾经做过实验,按照WeakReference的做法,编写程序,在android2.2上,程序运行正常
但是,同一套代码运行在android4.0上,程序崩溃:out of memory
正是为了避免OOM异常,我采用了WeakReference
但是,,,,,

WeakReference,不靠谱
在2.2 vs 4.0上

### Java 中内存泄漏的概念及原因 #### 内存泄漏定义 内存泄漏指的是程序中的无用对象(即不再使用的对象)仍然占据着内存空间,这些对象无法被垃圾回收器(Garbage Collector, GC)回收。随着运行时间的增长,这种未释放的内存可能会逐渐累积,最终导致应用程序耗尽可用内存并抛出 `OutOfMemoryError` 错误[^3]。 #### 常见的内存泄漏原因 1. **静态集合类引起的内存泄漏** 当使用静态集合类(如 `HashMap`, `ArrayList` 等)存储对象时,如果这些对象的生命周期超过了预期范围,则可能导致内存泄漏。这是因为静态变量的生命周期与应用相同,在应用关闭之前不会被回收。因此,即使某些对象已经不需要再使用,但由于它们仍存在于静态集合中,GC 将无法对其进行清理[^1]。 2. **内部类和匿名类对外部类实例的隐式引用** 在 Java 中,非静态内部类会持有一个指向外部类实例的隐藏引用。如果将这样的内部类实例(比如通过回调接口传递给另一个组件)保存在一个长时间存活的对象里,那么它同样也会阻止外部类实例被回收,进而引发潜在的内存问题。 3. **单例模式不当实现** 单例模式下的对象在整个应用程序期间都保持活动状态。如果该单例持有任何短生命期对象的强引用,并且这些对象本应更早地被释放掉的话,就会发生内存泄漏现象。 4. **监听器/事件处理器注册却未注销** 如果某个对象注册了一个全局广播接收者或者视图上的点击监听器等之后忘记解除绑定,那么只要那个源还活着,目标就不会被销毁,形成了一种间接形式的记忆残留情况。 5. **Handler 导致的内存泄露** 使用 Android 开发过程中常见的一种问题是由于 Handler 所造成的记忆流失隐患。具体来说就是当一个带有上下文参数 (Context) 的 handler 被创建出来以后又被长期存在的实体所拥有——例如作为成员字段的一部分或者是放在静态域当中——即便关联 activity 已经结束了自己的使命周期也不能正常退出堆栈之外因为还有别的地方牵连着它;与此同时假如说这个 handler 正好又绑定了定时任务之类的操作则更加剧了此类风险的存在可能性[^4]。 6. **缓存机制设计不合理** 缓存数据如果没有设置合适的淘汰策略也可能成为另一大诱因之一。特别是那些基于哈希表结构构建起来的大规模分布式系统里面经常需要用到各种类型的高速缓冲区来提升性能表现的同时也要注意防止过度膨胀带来的负面效应影响整体稳定性以及资源利用率等方面考量因素的重要性不可忽视。 --- ### 解决方案 针对上述提到的各种可能引起 java 应用程序内的 memory leak 场景分别给出对应的预防措施如下: 1. 对于由 Static Collection Class 引起的问题可以通过定期清除容器内过期条目或是采用弱引用 WeakReference 来代替传统方式处理键值对关系从而降低保留不必要的对象几率达到优化目的; 2. 避免让 Non-static Inner Classes 存在于 Global Scope 下面并且尽量减少其数量级以便更好地控制整个项目的复杂程度同时也方便后续维护工作开展顺利进行下去不至于陷入混乱局面难以自拔的地步; 3. 设计 Singleton Pattern 实现的时候要特别留意其中涉及到的所有依赖项是否均具备恰当的作用期限属性以免相互之间产生冲突矛盾之处阻碍正常的业务流程运转效率下降甚至崩溃事故频发等问题接踵而来令人头疼不已; 4. 注册 Listener / Callbacks 后务必记得适时调用相应方法将其移除以切断两者之间的联系链条使得各自能够独立完成各自的职责而不受对方干扰制约彼此自由行动的空间更大一些效果更好一点; 5. 关于 Handler Leak 方面可以考虑利用 Postponeable Runnable 技巧规避此陷阱另外还可以尝试引入第三方库帮助简化代码逻辑提高可读性和健壮性水平等等都是不错的思路值得借鉴学习一番看看能否适用于自己的实际应用场景之中去实践检验一下成果如何再说吧! 6. Cache Mechanism Design Should Be Carefully Considered With Proper Eviction Policies In Place To Ensure That It Does Not Grow Indefinitely And Consume Excessive Amount Of Resources Which Could Potentially Lead To Memory Exhaustion Issues Over Time If Left Unchecked. ```java // Example of using weak reference to prevent memory leaks in caches. import java.lang.ref.WeakReference; import java.util.HashMap; public class MyCache<K,V> extends HashMap<K,WeakReference<V>> { public V put(K key, V value){ return super.put(key,new WeakReference<>(value)).get(); } } ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值