java reference 类型简介
在日常的java开发中,我们很多时候都是通过以下方式创建对象和引用
Person person = new Person()
这里创建的就是一个强引用,那么有人就会说了,难道还有其他类型的引用,答案是肯定的,在java中包含四种类型的引用
一、强引用
如上所叙述,这种直接创建引用的都属于强引用,生命周期,引用与对象的指向关系没有去掉之前,对象在gc阶段不能被回收
二、弱引用
相对与强引用来说,弱引用在gc阶段,引用所指向的对象将被强制的回收
弱引用的创建方式
public static void main(String[] args) {
WeakReference<Integer> weakRef = new WeakReference(128);
System.out.println("GC前:"+weakRef.get());
System.gc();
System.out.println("GC后:"+weakRef.get());
}
上述代码的运行结果:
GC前:128
GC后:null
由此我们可以看到,执行了System.gc操作,弱引用的对象已经被回收了,注意:这里之所以用128,因为对于整数来说,-128~127的值使用的是缓存里的值,不会被回收
三、软引用
软引用只会在内存不足的情况下才会进行回收,如果内存充足,则不回收
用例如下:
public static void main(String[] args) {
//定义一个软引用列表
List<SoftReference<Integer>> softList = new ArrayList<>();
for(int i=0;i<5000;i++){
softList.add(new SoftReference<Integer>(new Integer(i)));
}
//存活的引用数
int activeRefNum = 0;
for(SoftReference softRef:softList){
if(softRef.get()!=null){
activeRefNum++;
}
}
System.out.println("当前存活的引用数:"+activeRefNum);
List list = new ArrayList();
for(int i=0;i<10000;i++){
list.add(i);
}
activeRefNum = 0;
for(SoftReference softRef:softList){
if(softRef.get()!=null){
activeRefNum++;
}
}
System.out.println("当前存活的引用数:"+activeRefNum);
}
当内存充足的情况下执行结果如下
GC前存活的软引用数:5000
GC后存活的软引用数:5000
当设置jvm 运行参数为 -Xms1m -Xmx1m
,执行结果如下:
GC前存活的软引用数:5000
GC后存活的软引用数:0
四、虚引用
虚引用,一种较为特殊的引用,该引用不能拿来存值,当你创建了虚引用以后,你不能通过get方法来获取值,相当于没有引用,这个引用主要可以拿来作为监控使用,因为当垃圾回收器确定回收对象的时候,会把引用放入到ReferenceQueue中,可以通过poll queue获取当前要被回收的引用对象
jvm参数:-Xms5m -Xmx5m
public static void main(String[] args) {
final ReferenceQueue queue = new ReferenceQueue();
PhantomReference<Integer> phantomRef = new PhantomReference<>(128,queue);
//start一个线程进行监控
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
Reference ref = queue.poll();
if(ref!=null){
System.out.println("--- 虚引用对象被jvm回收了 ----");
System.exit(1);
}
}
}
}).start();
//初始化一个list,不停的添加数据,出发jvm gc
List list = new ArrayList();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
list.add(new byte[1024 * 50]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("phantomRef的referent:"+phantomRef.get());
}
}
}).start();
}
执行结果如下:
phantomRef的referent:null
phantomRef的referent:null
phantomRef的referent:null
--- 虚引用对象被jvm回收了 ----