Java:References
Java引用类型
Strong References
默认的引用方式,即通过MyClass obj = new MyClass ();
这种方式赋值的对象,如果其存在active引用(从GC Root reachable)的话,是不会被回收的。如果内存不够,会抛出OOM异常。
Weak References
如果一个对象只能被弱引用访问(不存在强引用或者软引用的情况),那么下一次GC将被清理掉。
其主要的使用场景是实现canonicalizing mappings。即对于一个特定的value,map中只有一个instance。
Weak references allow you to leverage the garbage collector's ability to determine reachability for you, so you don't have to do it yourself.
WeakHashMap
WeakHashMap的key是使用的WeakReference,当某个key不再被使用的时候整个entry会被GC掉。这种设计里面的key主要面向的是按引用比较的对象,即equals里面按照==操作符进行比较(object identity)。WeakHashMap对于按值比较的对象,例如String,使用起来完全没有问题,但是因为String是可以recreate的,因此有时候会比较confusing。
WeakHashMap may behave as though an unknown thread is silently removing entries.
因为其中的value是强引用,使用的时候应该避免value中又去引用key的情况,否则会导致这个entry无法被回收。
典型使用WeakHashMap的场景是caching或者存储类的元数据。
Remember that WeakHashMap is useful only if the desired lifetime of cache entries is determined by external references to the key, not the value.
Soft References
软引用的对象在JVM内存不足的时候会被回收掉。
Phantom References
作用
PhantomReference(虚引用) 无法直接获取被引用的对象,必须跟ReferenceQueue一起使用。PhantomReference最弱,发生GC时会被回收,当JVM执行完finalize
之后,对象会被放到ReferenceQueue中。
Gfg g = new Gfg();
ReferenceQueue<Gfg> refQueue = new ReferenceQueue<>();
PhantomReference<Gfg> phantomRef = new PhantomReference<>(g, refQueue);
// 当g(强引用)不继续存在之后,对象就会被可以回收了
// 但在对象
g = null;
//It always returns null.
g = phantomRef.get();
使用场景
其使用场景主要有两种:
- 检测对象何时被回收,例如在执行对内存敏感的任务的时候,等待大对象回收了再开始新的任务
- 避免直接执行finalize,
Object.finalize()
在Java9中被标为Deprecated了,The Cleaner and PhantomReference provide more flexible and efficient ways to release resources when an object becomes unreachable.
直接执行finalize有什么问题呢?
Finalization can lead to performance issues, deadlocks, and hangs. Errors in finalizers can lead to resource leaks; there is no way to cancel finalization if it is no longer necessary; and no ordering is specified among calls to finalize methods of different objects.