Java内存管理包括内存分配和内存回收。
- 内存分配:程序员通过new对象,JVM会自动为该对象分配内存。
- 内存回收:Java在JVM虚拟机上增加了垃圾回收(Garbage Collection)机制,用以在合适的时间触发垃圾回收,将不需要的内存空间回收释放,避免无限制的内存增长导致的OOM.
其实GC时主要看这个对象是否有引用指向该对象。按照这种引用的强弱的关系, 从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。
四种引用
- 强引用(StrongReference)
- 是指创建一个对象并把这个对象赋给一个引用变量。比如 Object tv = new Object();
- 强引用有引用变量指向时永远不会被垃圾回收,JVM宁愿抛出OutOfMemory错误也不会回收这种对象。
- 如果程序确实不在用到某个强引用变量,通常可以手动将这个引用指向赋值为null。比如常见的集合中 claer() 方法。下面这段代码就是 ArrayList 的 clear()
/** * Removes all of the elements from this list. The list will * be empty after this call returns. */ public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; }
2.软引用(SoftReference)
SoftReference<T> softRef = new SoftReference<>(T t); softRef.get()
3.弱引用(WeakReference)
WeakReference<T> weakRef = new WeakReference<>(T t); weakRef.get()
4.虚引用(PhantomReferece)
- 顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。
- 任何时候都可以被GC回收,引用是最弱的。
- ReferenceQueue queue = new ReferenceQueue ();
- PhantomReference pr = new PhantomReference (object, queue);
- 由于引用关系最弱,并且源码中的get方法直接返回null,所以必须配合ReferenceQueue<T>使用
public T get() { return null; }
Q:Android中为什么不推荐使用软引用(SoftReference)?
Avoid Soft References for Caching
In practice, soft references are inefficient for caching. The runtime doesn't have enough information on which references to clear and which to keep. Most fatally, it doesn't know what to do when given the choice between clearing a soft reference and growing the heap.
在实践中,软引用(soft references)在缓存中是低效的,因为runtime并没有足够的信息来判别应该清除或者保留哪个 SoftReference(持有的对象),更无法判定当 App 要求更多内存的时候,是应该清除 SoftReference,还是增大 App 的Heap。
The lack of information on the value to your application of each reference limits the usefulness of soft references. References that are cleared too early cause unnecessary work; those that are cleared too late waste memory.
你的程序的引用的信息的缺失导致软引用用处的局限性。过早清除的引用会导致无用功,太晚清除又会浪费内存。
Most applications should use an android.util.LruCache instead of soft references. LruCache has an effective eviction policy and lets the user tune how much memory is allotted.
大多数程序应该使用android.util.LruCache来替代软引用,LruCache有着更高效的回收策略,并让用户协调要分配多少内存。
Q:如果一个对象同时有强引用和弱引用与之关联,那GC的时候会回收吗?
伪代码 T t = new T(); WeakReference<T> tRef = new WeakReference<>(t);
很显然GC的时候这个t不仅有弱引用还有强引用关联,此时是不会回收的。
Q: 既然虚引用形同虚设,那么它有什么作用?
网上找这样的描述:
- Use Cases
- There’re two common use-cases they are used for.
- The first technique is to determine when an object was removed from the memory which helps to schedule memory-sensitive tasks. For example, we can wait for a large object to be removed before loading another one.
- The second practice is to avoid using the finalize method and improve the finalization process.
第一个就是能够知道这个对象回收时机,能在对象被GC时收到系统通知
第二个就是避免使用 finalize
由于目前没有真正用过虚引用,欢迎补充,多谢~~