Object的finalize()方法的作用是否与C++的析构函数作用相同
public class Finalization {
private static Finalization finalization;
/**finalize在gc回收中有不确定性,所以不推荐用finalize进行回收*/
@Override
protected void finalize(){
System.out.println("finalized");
//System.gc()时,这一步可能没有被执行到就终止了,所以可能为null或对象地址。
//可以让线程睡眠执行此步骤
finalization=this;
}
public static void main(String[] args) {
Finalization f = new Finalization();
System.out.println("first print: "+f);
f= null;
//调用Finalization的finalize方法
System.gc();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("second print: "+f);
System.out.println(finalization);
}
}
未加入线程休眠的代码,发现finalization可能输出为null
first print: com.gclhaha.javabasic.jvm.gc.Finalization@1b6d3586
second print: null
finalized
null
加入休眠代码后
first print: com.gclhaha.javabasic.jvm.gc.Finalization@1b6d3586
finalized
second print: null
com.gclhaha.javabasic.jvm.gc.Finalization@1b6d3586
Java中强引用、软引用、弱引用、虚引用有什么用
强引用
软引用
软引用还可以配合引用队列去使用
弱引用
弱引用还可以配合引用队列去使用
虚引用
gc在回收对象时,这个对象具有虚引用,那么在回收前,回将虚引用加入引用队列中,通过判断引用队列中是否加入虚引用来了解被引用的对象是否被gc回收,可以起到哨兵的作用。
软引用和弱引用也可以先像上面这样配合ReferenceQueue使用。
总结
引用队列(ReferenceQueue)
public class ReferenceQueue<T> {
static private class Lock { };
private Lock lock = new Lock();
private volatile Reference<? extends T> head = null;
private long queueLength = 0;
由上面可以看到ReferenceQueue中只存储了一个head属性,进入Reference看一下
public abstract class Reference<T> {
private T referent; /* Treated specially by GC */
volatile ReferenceQueue<? super T> queue;
/* When active: NULL
* pending: this
* Enqueued: next reference in queue (or this if last)
* Inactive: this
*/
@SuppressWarnings("rawtypes")
volatile Reference next;
其中,referent
保留了创建对象的引用,next
指向queue的下一个节点。
ReferenceQueue通过poll
和enqueue
remove
来操作队列
Demo
NormalObject
重写finalize
方法
public class NormalObject {
String name;
NormalObject(String name){
this.name = name;
}
@Override
protected void finalize(){
System.out.println("finalizing NormalObject: "+name);
}
}
**NormalObjectWeakReference **
重写finalize
方法,创建构造方法
public class NormalObjectWeakReference extends WeakReference<NormalObject> {
String name;
NormalObjectWeakReference(NormalObject normalObject, ReferenceQueue<NormalObject> referenceQueue){
super(normalObject,referenceQueue);
this.name = normalObject.name;
}
@Override
protected void finalize(){
System.out.println("finalizing NormalObjectWeakReference: "+name);
}
}
ReferenceQueueTest
public class ReferenceQueueTest {
private static ReferenceQueue<NormalObject> rq = new ReferenceQueue<>();
private static void checkQueue(){
Reference<NormalObject> ref;
while ((ref = (Reference<NormalObject>)rq.poll()) != null){
if (ref != null){
System.out.println("in queue :"+((NormalObjectWeakReference)(ref)).name);
System.out.println("ref object: "+ref.get());
}
}
}
public static void main(String[] args) {
ArrayList<WeakReference<NormalObject>> weakList = new ArrayList<>();
for (int i = 0; i < 3; i++) {
weakList.add(new NormalObjectWeakReference(new NormalObject("weak"+i),rq));
System.out.println(weakList.get(i));
}
System.out.println("first time");
checkQueue();
System.gc();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("second time");
checkQueue();
}
}
分析一下,调用主方法,在weakList
中添加三个NormalObjectWeakReference
对象,打印三个对象的地址。输出first time
,调用checkqueue()
,没有输出in queue
,代表着三个对象并没有被添加到referenceQueue
,调用gc()
,NormalObject
的finalize()
输出finalizing NormalObject: weak1/2/3
,输出second time
,再调用checkqueue()
,这时队列不为空,输出内容,ref
此时为null
打印结果
com.gclhaha.javabasic.jvm.gc.NormalObjectWeakReference@7f31245a
com.gclhaha.javabasic.jvm.gc.NormalObjectWeakReference@6d6f6e28
com.gclhaha.javabasic.jvm.gc.NormalObjectWeakReference@135fbaa4
first time
finalizing NormalObjec
finalizing NormalObject: weak1
finalizing NormalObject: weak0
second time
in queue :weak0
ref object: null
in queue :weak2
ref object: null
in queue :weak1
ref object: null