java引用类型
- 强引用:当内存不足的时候,都不会进行空间回收,最终JVM抛出OutOfMemoryError
- 软引用:当内存不足的时候,进行对象的回收处理,往往用于高速缓存中
- 弱引用:不管内存是否紧张,只要GC运行都会回收
- 幽灵引用:和没引用一样。
强引用
- JVM默认支持模式
- 在引用期间内,如果该堆内存被指定的栈内存有联系,那该对象就无法被GC所回收
- 一旦出现内存不足,就会出现OutOfMemoryError异常
- 正因为强引用具备内存分配异常问题,因此尽量少实例化对象
测试程序:
package cn.liang.jvm;
import static org.hamcrest.CoreMatchers.nullValue;
import java.lang.ref.SoftReference;
public class referenceType2 {
public static void main(String[] args) {
Object object = new Object();
Object ref = object;
object = null;
System.out.println("内存充足时进行gc回收:");
System.gc();
System.out.println(ref);
System.out.println("内存不足时进行gc回收:");
try {
String string = "liangjingfu";
while (true) {
string += string + string;
string.intern();
}
} catch (Throwable e) {
}
System.out.println(ref);
}
}
输出结果:
内存充足时进行gc回收:
java.lang.Object@7852e922
内存不足时进行gc回收:
java.lang.Object@7852e922
软引用
- 在许多的开源组件中,往往会使用软引用作为缓存组件出现
- 软引用不足时回收,不充足时不回收
- 软引用需要一个单独的类来实现控制:java.lang.ref.SoftReference
- 构造函数:public SoftReference(T referent)
- 取出数据:public T get();
测试程序:
package cn.liang.jvm;
import static org.hamcrest.CoreMatchers.nullValue;
import java.lang.ref.SoftReference;
public class referenceType2 {
public static void main(String[] args) {
Object object = new Object();
SoftReference<Object> ref = new SoftReference<Object>(object);
object = null;
System.out.println("内存充足时进行gc回收:");
System.gc();
System.out.println(ref.get());
System.out.println("内存不足时进行gc回收:");
try {
String string = "liangjingfu";
while (true) {
string += string + string;
string.intern();
}
} catch (Throwable e) {
}
System.out.println(ref.get());
}
}
输出结果:
内存充足时进行gc回收:
java.lang.Object@7852e922
内存不足时进行gc回收:
null
弱引用:
- 只要一进行GC处理,那么所引用的对象将会立即回收
- 弱引用需要使用Map接口的子类:java.util.WeakHashMap
- java.lang.ref包中存在一个WeakReference子类
测试程序1:
package cn.liang.jvm;
import java.util.Map;
import java.util.WeakHashMap;
public class referenceType3 {
public static void main(String[] args) {
String keyString = new String("name");
String valueString = new String("liang");
Map<String, String> map = new WeakHashMap<String, String>();
map.put(keyString, valueString);
keyString = null;
System.out.println("内存进行gc回收前:");
System.out.println(map);
System.out.println("内存进行gc回收后:");
System.gc();
System.out.println(map);
}
}
输出结果:
内存进行gc回收前:
{name=liang}
内存进行gc回收后:
{}
测试程序2:
package cn.liang.jvm;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
public class referenceType3 {
public static void main(String[] args) {
String keyString = new String("liang");
WeakReference<String> reference = new WeakReference<String>(keyString);
keyString = null;
System.out.println("内存进行gc回收前:");
System.out.println(reference.get());
System.gc();
System.out.println("内存进行gc回收后:");
System.out.println(reference.get());
}
}
输出结果:
内存进行gc回收前:
liang
内存进行gc回收后:
null
引用队列
- 主要是保存那些准备被回收的对象
- 所有的对象的回收扫描都是从根对象开始的
- 引用路径的设置即确定好哪些对象可以被回收后,设置相应的引用强度
- 引用队列可避免非强引用对象所带来的内存引用问题,该对象被回收后会自动保存
- 找到对象5有两个路径:
- 对象1 --> 对象5(强 + 软)
- 对象2 --> 对象5(强 + 弱)
测试程序:
package cn.liang.jvm;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
public class referenceType4 {
public static void main(String[] args) throws Exception {
Object obj = new Object();
ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
WeakReference<Object> reference = new WeakReference<Object>(obj,queue);
System.out.println("内存进行gc回收前:");
System.out.println(queue.poll());
obj = null;
System.gc();
Thread.sleep(100);
System.out.println("内存进行gc回收后,对象保存:");
System.out.println(queue.poll());
}
}
输出结果:
内存进行gc回收前:
null
内存进行gc回收后,对象保存:
java.lang.ref.WeakReference@7852e922
幽灵引用
测试程序:
package cn.liang.jvm;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
public class referenceType5 {
public static void main(String[] args) throws Exception {
Object obj = new Object();
ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
PhantomReference<Object> reference = new PhantomReference<Object>(obj,queue);
System.gc();
System.out.println("对象读取:");
System.out.println(reference.get());
System.out.println("对象保存后读取:");
System.out.println(queue.poll());
}
}
输出结果:
对象读取:
null
对象保存后读取:
null