在finalize的执行来看什么是GC Root我们测试了不同GC Root可达时,对对象finalize方法的执行的影响。下面我们测试一下不同引用对对象finalize方法的执行的影响。
public class RootTest {
static int gcTime = 0;
public static void main(String[] args) throws InterruptedException {
SoftReference softReference = new SoftReference<>(new UnusedLock("soft reference"));
WeakReference weakReference = new WeakReference<>(new UnusedLock("weak reference"));
new UnusedLock("no reference");
UnusedLock unusedLock = new UnusedLock("strong reference");
new Thread() {
@Override
public void run() {
int x = 0;
synchronized (new UsedLock()) {
while (x < 3) {
System.out.println("Thread run " + ++x);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread run over");
}
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("Thread finalize() " + Thread.currentThread().getName());
}
}.start();
gc();
Thread.sleep(5000);
gc();
Thread.sleep(5000);
}
static void gc() {
System.out.println("gc start " + ++gcTime);
System.gc();
System.out.println("gc over " + gcTime);
}
}
class UsedLock {
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("UsedLock finalize()");
}
}
class UnusedLock {
private String sign = null;
public UnusedLock(String sign) {
this.sign = sign;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("UnusedLock finalize(): " + sign);
}
}
我们分别使用软引用、弱引用、强引用以及不引用来测试对象finalize方法的执行
运行结果:
Thread run 1
gc start 1
UnusedLock finalize(): no reference
UnusedLock finalize(): weak reference
gc over 1
Thread run 2
Thread run 3
Thread run over
gc start 2
gc over 2
UsedLock finalize()
Thread finalize() Finalizer
可见,第一次执行gc时,没有被引用的对象和弱引用的对象finalze方法被调用,软引用和强引用的对象finalze方法没有被调用。
第二次执行gc时,软引用和强引用的对象finalze方法也没有被调用。
我们来模拟一下内存不足时的情况,代码如下:
public class RootTest {
static int gcTime = 0;
public static void main(String[] args) throws InterruptedException {
SoftReference softReference = new SoftReference<>(new UnusedLock("soft reference"));
WeakReference weakReference = new WeakReference<>(new UnusedLock("weak reference"));
new UnusedLock("no reference");
UnusedLock unusedLock = new UnusedLock("strong reference");
byte[] bytes = new byte[1024 * 1024 * 1024];
System.out.println(bytes.length);
bytes = new byte[1024 * 1024 * 1024];
System.out.println(bytes.length);
new Thread() {
@Override
public void run() {
int x = 0;
synchronized (new UsedLock()) {
while (x < 3) {
System.out.println("Thread run " + ++x);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread run over");
}
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("Thread finalize() " + Thread.currentThread().getName());
}
}.start();
// gc();
// Thread.sleep(5000);
// gc();
// Thread.sleep(5000);
}
static void gc() {
System.out.println("gc start " + ++gcTime);
System.gc();
System.out.println("gc over " + gcTime);
}
}
class UsedLock {
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("UsedLock finalize()");
}
}
class UnusedLock {
private String sign = null;
public UnusedLock(String sign) {
this.sign = sign;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("UnusedLock finalize(): " + sign);
}
}
我们不再主动调用gc了,直接分两次申请1024 * 1024 * 1024 byte的内存,看下运行结果:
1073741824
UnusedLock finalize(): soft reference
UnusedLock finalize(): no reference
UnusedLock finalize(): weak reference
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at at.miao.java_lib.RootTest.main(RootTest.java:17)
可见,第一次申请成功了,但是第二次申请的时候内存不足了,这时候软引用、无引用、弱引用的对象finalize方法都被调用了,对象被回收后剩余内存还是不足,造成了OutOfMemoryError。
软引用会在内存不足时被GC回收。