- Object的finalize()方法是否与C++的析构函数是一样的
答案是不同的,因为析构函数的调用是确定的,而finalize是不确定的,假如一个java的方法,经历过第一次可达性分析的时候,发现并没有和GC ROOTS相连,那么就会去判断是否被finalize覆盖,如果是,就会被放进F-Queue队列中,最后由JVM的finalize去回收这个方法。缺点就是finalize覆盖的方法随时都有可能会被终结,而不是一定等运行结束后,但是意义在于可以给一个方法一次逃脱被回收的机会。
写一个程序来验证一下:
程序思路是:首先我们new 一个对象,然后打印出来,是没问题的。然后我们手动触发gc,gc触发finalize方法,此时打印出Finalized,而f因为我们上面进行了赋值,所以变成了null,但是finalization的这个属性,又将该对象重新赋值回去,于是最后打印出f的地址。
但是问题在于刚才说的,有可能gc还没执行完(也就是说finalize方法还没执行完),就执行下面的程序了,那么最后一个打印的f.finalization就会是null,这是我们不想看见的,所以我们可以加一个sleep,保证gc完整执行。
- Java中的强引用,软引用,弱引用,虚引用有什么作用?
- 强引用
最普遍的引用
Object obj = new Object();
最后就算因为内存不足,抛出oom终止程序,也不会因此而回收强引用产生的对象实例。如果我们想回收强引用的对象,就需要将对象设置为null来弱化引用,使其被回收。
- 软引用
是一种相对强引用弱化一些的引用,可以让对象豁免一些垃圾收集,只有当JVM认为内存不足时,才会去试图回收软引用指向的对象。JVM会确保在抛 出OutOfMemoryError之前,清理软引用指向的对象。软引用通常用来实现内存敏感的缓存,如果还有空闲内存,就可以暂时保留缓存,当内存不足时清理掉,这样就保证了使用缓存的同时,不会耗尽内存。
String str = new String("abc");//强引用
SoftReference<String> softRef = new SoftReference<String>(str);//软引用
- 弱引用
比软引用的声明更加弱,在GC的时候,不管内存缺不缺都会被直接回收,但是由于GC线程的执行优先级比较低,所以被回收的概率也不是很高,适用于引用偶尔被使用,但是不影响垃圾收集的对象。
String str = new String("abc");
WeakReference<String> wr = new WeakReference<String>(str);
- 虚引用
虚引用不会影响对象的生命周期,它会在任何时候都有可能被垃圾回收,主要的作用在于可以跟踪对象被垃圾回收器回收的活动,起到了哨兵的作用,但是必须与引用队列ReferenceQueue联合使用。
String str = new String("abc");
ReferenceQueue queue = new ReferenceQueue();
PhantomReference ref = new PhantomReference(str,queue);
在GC的时候,如果发现了有虚引用的情况,会首先将其加入到引用队列中,程序可以判断引用队列的对象就能判断这个对象是否被垃圾回收了。
- 引用队列(ReferenceQueue)
没有实际的存储结构,但是可以理解成链表,它的存储依赖于内部节点之间的关系来表达,就像是leetcode的题,next连接node。