ThreadLocal
ThreadLocalMap.Entry extends WeakReference<ThreadLocal<T>>
但是T: referent 不是WeakReference, ThreadLocal.set-->ThreadLocalMap.set new Entry -->rehash-->expungeStaleEntries() /***** Expunge all stale entries in the table. *****/
强引用(StrongReference)
软引用(SoftReference)
弱引用(WeakReference)[一个对象若只被弱引用所引用,则被认为是不可访问(或弱可访问)的,并因此可能在任何时刻被回收]
虚引用(PhantomReference)
1.强引用(StrongReference)
强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
2.软引用(SoftReference)
如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
3.弱引用(WeakReference)
弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
当Java回收器遇到了弱引用的时候有可能会执行以下操作:
【1】将WeakReference对象的referent域设置成为null,从而使该对象不再引用heap对象。
【2】WeakReference引用过的内存堆上的对象一律被生命为finalizable。
【3】当内存堆上的对象finalize()方法被运行而且该对象占用的内存被释放,WeakReference对象就会被添加到它的ReferenceQueue,前提条件是ReferenceQueue本身是存在的。
4.虚引用(PhantomReference)
“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。
WeakHashMap e.g
使用场景:当映射的生命周期必须与键的生命周期联系在一起时。
WeakHashMap的Key是弱引用,Value不是。
WeakHashMap不会自动释放失效的弱引用,仅当包含了expungeStaleEntries()的共有方法被调用的时候才会释放。
配合使用引用队列 ReferenceQueue
WeakHashMap 用弱引用承载映射键,这使得应用程序不再使用键对象时它们可以被垃圾收集,get() 实现可以根据 WeakReference.get() 是否返回 null 来区分死的映射和活的映射。但是这只是防止 Map 的内存消耗在应用程序的生命周期中不断增加所需要做的工作的一半,还需要做一些工作以便在键对象被收集后从 Map 中删除死项。否则,Map 会充满对应于死键的项。虽然这对于应用程序是不可见的,但是它仍然会造成应用程序耗尽内存。
引用队列是垃圾收集器向应用程序返回关于对象生命周期的信息的主要方法。弱引用有两个构造函数:一个只取 referent 作为参数,另一个还取引用队列作为参数。如果用关联的引用队列创建弱引用,在 referent 成为 GC 候选对象时,这个引用对象(不是 referent)就在引用清除后加入 到引用队列中。之后,应用程序从引用队列提取引用并了解到它的 referent 已被收集,因此可以进行相应的清理活动,如去掉已不在弱集合中的对象的项。(引用队列提供了与 BlockingQueue 同样的出列模式 —— polled、timed blocking 和 untimed blocking。)
WeakHashMap 有一个名为 expungeStaleEntries() 的私有方法,大多数 Map 操作中会调用它,它去掉引用队列中所有失效的引用,并删除关联的映射。
为避免“我们所谓的”内存泄露:
1. ThreadLocal<WeakReference<T>>,将referent包裹成WeakReference。
2. 构建自定义ThreadLocal,并且为非静态数据成员。
[在业务应用中]应该远离这些Java特性!!! 这是架构师的issue :
反射
字节码操纵
ThreadLocal
类加载器
弱引用与软引用
Sockets
相关推荐
在JDK 8之前,这个内部Map是`ThreadLocal.ThreadLocalMap`,而从JDK 8开始,改为了`WeakReference<ThreadLocal<?>>`和`Object`的组合,提高了内存管理效率。 **JDK 8之前的ThreadLocalMap** 在JDK 8之前,...
- `ThreadLocal`类在`java.lang`包下,它的实现主要依赖于`Thread`类的成员变量`threadLocals`,这是一个`ThreadLocalMap`实例,`ThreadLocalMap`是`WeakReference<ThreadLocal<?>>`和`Object`(代表值)的键值对...
其次,ThreadLocalMap 是 ThreadLocal 中定义的一个类,可以简单地将它理解成一个 Map,不过它的 key 是 WeakReference 弱引用类型。这意味着,当这个值没有在别的地方引用时,在发生垃圾回收时,这个 map 的 key 会...
由于ThreadLocalMap的键是弱引用(WeakReference),当垃圾收集器清除时,键会被回收,但是值(即用户存储的对象)由于被ThreadLocalMap间接引用,所以不会被垃圾收集。这样,这些无用的对象会一直占用内存,直到...
ThreadLocalMap并不直接继承自java.util.Map,而是使用WeakReference来保存ThreadLocal实例作为键。这样做的好处是,当一个ThreadLocal变量不再被引用时,可以被垃圾收集器回收,避免内存泄漏。而Value部分则存储了...
ThreadLocalMap的实现使用了弱引用(WeakReference<ThreadLocal<?>>)作为key,这是因为即使没有外部引用指向ThreadLocal实例,只要它还在ThreadLocalMap中作为key存在,垃圾收集器就不会回收ThreadLocal实例。...
通过阅读源码,我们可以发现ThreadLocalMap实际上是一个内部类,继承自WeakReference,这样的设计是为了尝试解决内存泄漏问题,但并不能完全避免。 总之,ThreadLocal是Java中一个非常实用的工具,它提供了一种简单...
- 示例:`WeakReference sr = new WeakReference(new String("hello"));` - ThreadLocal 内部使用弱引用来管理线程局部变量,当线程退出或者 ThreadLocal 对象被置为 null,对应的弱引用对象会被回收。 4. 虚引用...
ThreadLocalMap是ThreadLocal的内部类,它使用Entry数组来存储数据,而Entry是ThreadLocalMap的静态内部类,继承了WeakReference<ThreadLocal<?>>。 ### 知识点二:ThreadLocal的set方法 ThreadLocal的set方法用于...
ThreadLocalMap中的Entry继承自WeakReference,这是为了避免内存泄露。因为如果不使用弱引用,一旦ThreadLocal实例在代码中被废弃,但仍然保留在ThreadLocalMap中,就会形成内存泄漏。由于Entry的key是弱引用,当...
2. **Entry**:`ThreadLocalMap`的内部类`Entry`继承自`WeakReference<ThreadLocal<?>>`,这意味着`ThreadLocal`对象是弱引用,当没有其他强引用指向`ThreadLocal`时,它将被垃圾回收,对应的`Entry`也会在下次`...
ThreadLocalMap的实现使用了Entry类,Entry是ThreadLocal的一个静态内部类,它继承自WeakReference<ThreadLocal<?>>。这意味着ThreadLocal对象作为键是弱引用,当ThreadLocal对象不再被引用时,垃圾收集器可以回收它...
弱引用使用WeakReference帮助我们定义弱引用。弱引用的特点是只要有垃圾回收,弱引用的对象就会被回收。弱引用可以用来缓存对象,但不能用来保存重要的对象。 4. 虚引用(Phantom Reference): 虚引用使用...
2.避免使用ThreadLocal:尽量少用ThreadLocal,或者使用WeakReference来避免强引用。 3.正确使用ClassLoader:确保ClassLoader被正确释放,以免加载的类无法被卸载。 Java内存泄露是Java应用程序中一个常见的问题,...
- 使用WeakReference或软引用(SoftReference)包裹可能引发内存泄漏的对象。 - 在不再使用时,及时断开对Context、View、BroadcastReceiver等的引用。 - 注意Handler可能导致的内存泄漏,特别是在Activity销毁后...
- 避免内存泄漏,特别是使用`WeakReference`或`SoftReference`时需谨慎处理。 - 考虑到类加载机制和静态初始化,理解不同实现方式的优缺点。 在压缩包文件"test"中,可能包含了实现这些线程相关单例模式的代码示例...
但在某些情况下,如使用了WeakReference、SoftReference等弱引用,或者有线程局部变量(ThreadLocal)未正确清理,就可能导致类加载器无法被回收,从而引发内存泄露。 三、内存泄露的诊断方法 1. **使用工具辅助...
为避免这类问题,应避免使用静态变量引用Context,优先使用ApplicationContext,或者使用WeakReference弱引用。 线程也是引发内存泄露的常见原因。线程内部持有的对象如果长时间存活,可能会导致原本应被释放的对象...
解决内存泄漏可以采取以下措施:避免静态引用非静态对象,使用弱引用(如WeakReference)引用外部类,正确释放资源,及时取消注册监听器,以及避免在非静态内部类中使用this引用。 以上是Android面试中常见的原理...