内存溢出解决方案: java.lang.ref 包

首先,看下jdk 中, java.lang.ref包的具体类体系:

                           内存溢出解决方案: java.lang.ref 包_第1张图片

名词解释如下:

PhantomReference(幽灵引用,虚引用),  SoftReference ( 软引用),  WeakReference(弱引用)

先不管这些类设计的目的,让我们思考下: 

假设一个项目,高峰时期需要使用上万个某类的对象,但平时就使用几百个对象,我们是如何解决?

一般的步骤如下:    1,创建类-------》2,创建对象,调用方法

//创建自定义类: 假设为AA
//为观察垃圾回收的过程,需要重写finalize()
@Override
protected void finalize() throws Throwable {
	super.finalize();
	System.out.println(this.getClass().getName()+"-"+count+"--->回收");
}
public class RefTest {
	public static void main(String[] args) {
		
		AA[] arr=new AA[1000000];
		for (int i = 0; i < arr.length; i++) {
			arr[i]=new AA(i+"");
		}
		System.out.println(arr[0].getName());
		//回收内存
		System.gc();
		System.runFinalization();
		//再次访问信息
		System.out.println(arr[0].getName());
  }
}

由于堆内存中,创建的对象过多,并且持续占用空间,以上程序运行十分缓慢, 而且更有可能出现内存溢出的Error,

这就是: 强引用 !( 堆中的对象一直被栈中的变量所引用, 使得虚拟机不能回收内存 )


而java.lang.ref包的类,就是为此提供了一个解决方案, 具体演示如下:

虚引用===》跟踪对象的回收状态

//虚引用 + 队列=================》gc() 后,被引用的的对象,放在队列中
//作用:跟踪对象的--回收状态
	ReferenceQueue q = new ReferenceQueue<>();
	String st=new String("aaa");
	PhantomReference phr = new PhantomReference<>(st, q);
	System.out.println("before gc--->"+phr.get());//null
	System.out.println(q.poll()==phr);
		
	//回收变量
	st=null;
		
	System.gc();
	System.runFinalization();
		
	System.out.println("after gc--->"+phr.get());//null
	System.out.println(q.poll()==phr);//true:对象被回收后,虚引用--被添加到队列
执行结果:

内存溢出解决方案: java.lang.ref 包_第2张图片

1,软引用=====》自动内存回收:它所管理的对象会在内存不足时被清除

//软引用  ---模拟堆内存不足: -Xmx2m -Xms2m: 给定2m内存,程序会调用gc()回收
//作用: 当内存不足时, 其所管理的对象会自动删除,实现内存回收;内存够用时,不会自动回收
//所以要注意NullPointerException
	SoftReference[] arr=new SoftReference[7000];
		
	for(int i=0;i(new AA("--name-->"+i));
	}
	
	//获取对象信息
	System.out.println(arr[1].get());//AA@7852e922
	System.out.println(arr[2].get());//AA@4e25154f
	System.out.println(arr[3].get());//AA@70dea4e
			
	//回收内存
	System.gc();
	System.runFinalization();
			
	//再次访问信息
	System.out.println("==============");
	System.out.println(arr[1].get());//null
	System.out.println(arr[2].get());//null
	System.out.println(arr[3].get());//null
	System.out.println(arr.length);//7000
		

执行结果:

内存溢出解决方案: java.lang.ref 包_第3张图片

2,弱引用========》自动管理内存,同上

//弱引用==================测试
	String a=new String("name1");
	WeakReference w=new WeakReference(a);
	a=null;
	//查看信息
	System.out.println(w.get());//name1
		
	//回收内存
	System.gc();
	System.runFinalization();
		
	//查看信息
	System.out.println(w.get());//null
	

执行结果:

内存溢出解决方案: java.lang.ref 包_第4张图片


//弱引用=====>堆内存不足, gc()自动回收内存
	WeakReference[] arr=new WeakReference[4000];
			
	for(int i=0;i"+i));
	}
		
	//获取对象信息
	System.out.println(arr[1].get());//AA@7852e922
	System.out.println(arr[2].get());//AA@4e25154f
	System.out.println(arr[3].get());//AA@70dea4e
				
	//回收内存: 不强制调用gc()也会自动清理内存
	//System.gc();
	//System.runFinalization();
				
	//再次访问信息
	System.out.println(arr[1].get());//null
	System.out.println(arr[2].get());//null
	System.out.println(arr[3].get());//null
	

执行结果:

内存溢出解决方案: java.lang.ref 包_第5张图片


你可能感兴趣的:(编程语言-java)