强引用/软引用/弱引用/虚引用/终结器引用
强引用
直接通过new关键字等到的对象与变量之间的关系,是强引用,比如: byte []b = new byte[1024*1024*15]; String str = new String(); 这里是变量直接指向了byte数组对象.进行GC时,只要强引用存在,那么GC就不会进行回收,即使内存溢出也不会,这个时候便会内存溢出报异常.
软引用
通过SoftReference类实现:
SoftReference<byte[]> m = new SofReference<>(new byte[1024*1024*15]);
System.out.print(m.get());//打印软引用对象
这里是变量指向了一个SoftReference对象.SoftReference对象再指向byte数组对象,这个两个对象之间的引用是软引用.通过m.get()方法可以获得这个软引用的对象(byte数组)
▭(变量 m) → ◯(SoftReference对象) ⇢ █(实际的对象)
GC不会回收存在强引用的对象,对于软引用,如果内存空间足够,GC也不会回收软引用,当内存空间不够时,会回收软引用.例如: 分配的内存空间为20M,首先定义了一个软引用对象占用15M的空间,接着再定义一个强引用对象分配10M空间,强引用所需空间不够,此时GC会回收软引用对象的15M空间,然后将强引用对象放入.
软引用的作用:
适合作为缓存使用,将某些数据对象设置为软引用,当内存不够时很方便的直接通过GC回收,内存足够那就放在内存中,不动它,这样既节省内存也考虑到了效率.
弱引用
通过WeakReference类实现,
WeakReference<M> m = new WeakReference<>( new M() );
System.out.print(m.get());//打印弱引用对象,可以拿到
通过m.get()方法可以获得弱引用对象(M对象),弱引用在进行了GC后会直接被回收。
虚引用
虚引用的作用:
在JVM中管理直接内存,GC回收直接内存时才用到虚引用.其他情况不会用的.
Phantom:虚幻的;
虚引用通过PhantomReference类实现:
static final ReferenceQueue<M> QUEUE = new ReferenceQueue<>();//引用队列
PhantomReference<M> m = new PhantomReference<>( new M() , QUEUE);
System.out.print(m.get());//打印虚引用对象,结果为null,说明m.get()拿不到虚引用对象
直接内存:
通常情况下,对象是从JVM管理的内存中获取数据,JVM可以从OS中拷贝外界的数据; 但在JVM中提供了一种直接访问OS内存数据的方法,可以让JVM中的对象通过指针直接指向操纵系统上的某一块内存,这样加快了数据的访问速度.
**直接内存的实现使用到了虚引用 **
GC只能管理JVM内存,在直接内存的情况下,如果GC将JVM的对象回收了,那么该对象指向的OS中的内存该如何回收?所有的虚引用在GC回收时,所指向的对象会被自动的放到引用队列中,放入到队列中的对象一般会指向直接的OS内存,然后回收时由JVM去做单独的处理.
终结器引用
无需手动编码,但是内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由Finalizer线程通过线程终结器引用找到被引用对用并调用它的finalize方法,第二次GC时才能回收被引用对象.
由于终结器引用在垃圾回收时比较麻烦,所以一般不会用到终结器引用.