java的虚引用_java虚引用的使用说明

“为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。”

public static void main(String[] args) throws InterruptedException {

final ReferenceQueue referenceQueue = new ReferenceQueue<>();

new ScheduledThreadPoolExecutor(1,

new BasicThreadFactory.Builder().namingPattern("GC-Watcher-Thread-%d").daemon(true).build()).scheduleAtFixedRate(new Runnable() {

@Override

public void run() {

while (true) {

Reference reference = referenceQueue.poll();

if(reference != null) {

try {

Field referent = Reference.class.getDeclaredField("referent");

referent.setAccessible(true);

System.out.println("gc-->" + referent.get(reference));

} catch (NoSuchFieldException e) {

} catch (IllegalAccessException e) {

e.printStackTrace();

}

} else {

break;

}

}

}

}, 1, 1, TimeUnit.SECONDS);

String testStr = new String("test-str");

PhantomReference prTestStr = new PhantomReference(testStr, referenceQueue);

testStr = null;

Thread.sleep(1000L);

System.gc();

Thread.sleep(2000L);

}

当执行上述代码后:控制台将会打印: gc-->test-str

将上述代码改为如下方式:

static final ReferenceQueue referenceQueue = new ReferenceQueue<>();

public static void main(String[] args) throws InterruptedException {

new ScheduledThreadPoolExecutor(1,

new BasicThreadFactory.Builder().namingPattern("GC-Watcher-Thread-%d").daemon(true).build()).scheduleAtFixedRate(new Runnable() {

@Override

public void run() {

while (true) {

Reference reference = referenceQueue.poll();

if(reference != null) {

try {

Field referent = Reference.class.getDeclaredField("referent");

referent.setAccessible(true);

System.out.println(referent.get(reference));

} catch (NoSuchFieldException e) {

} catch (IllegalAccessException e) {

e.printStackTrace();

}

} else {

break;

}

}

}

}, 1, 1, TimeUnit.SECONDS);

test();

Thread.sleep(1000L);

System.gc();

Thread.sleep(2000L);

}

private static void test() {

String testStr = new String("test-str");

PhantomReference prTestStr = new PhantomReference(testStr, referenceQueue);

}

运行之后没有效果;原因是虚引用prTestStr被系统回收后就不会加到referenceQueue的queue内

将上述代码在做一次修改

static final List> prList = new ArrayList<>();

static final ReferenceQueue referenceQueue = new ReferenceQueue<>();

public static void main(String[] args) throws InterruptedException {

new ScheduledThreadPoolExecutor(1,

new BasicThreadFactory.Builder().namingPattern("GC-Watcher-Thread-%d").daemon(true).build()).scheduleAtFixedRate(new Runnable() {

@Override

public void run() {

while (true) {

Reference reference = referenceQueue.poll();

if(reference != null) {

try {

Field referent = Reference.class.getDeclaredField("referent");

referent.setAccessible(true);

prList.remove(reference);

System.out.println("gc-->" + referent.get(reference));

} catch (NoSuchFieldException e) {

} catch (IllegalAccessException e) {

e.printStackTrace();

}

} else {

break;

}

}

}

}, 1, 1, TimeUnit.SECONDS);

test();

Thread.sleep(1000L);

System.gc();

Thread.sleep(2000L);

}

private static void test() {

String testStr = new String("test-str");

PhantomReference prTestStr = new PhantomReference(testStr, referenceQueue);

prList.add(prTestStr);

}

当执行上述代码后:控制台又打印出了: gc-->test-str

这样我们就可以根据虚引用来跟踪一个对象是否被gc。当我们经常在代码里面使用缓存或者读写文件又或者使用jdbc,不合理的使用例如:使用的数据库连接未关闭

查询结果未关闭、文件流未关闭等等造成了内存泄漏。在我们不确定是否有内存被这些对象泄漏的时候,我们可以通过虚引用的方式进行监控跟踪相关对象在内存的垃圾回收情况

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值