java匿名类对象的坏处_Java匿名对象导致的内存泄漏

这几天与在某群与群友讨论了Runnable匿名对象导致内存泄漏的相关问题,特此记录一下。

示例代码如下:

packagecom.memleak.memleakdemo;public class Leaker {

String valueToRead= "Hello world";public voiddoSomething()

{

Thread bgThread= newThread(newRunnable()

{public voidrun() {while (true)

{

System.out.println("Running... ok");try{

Thread.sleep(1000);

}catch(InterruptedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

);

bgThread.start();

}

}

Main函数:

packagecom.memleak.memleakdemo;/*** Hello world!

**/

public classApp

{public static voidmain( String[] args )

{

Leaker l= newLeaker();

l.doSomething();

}

}

问题出在哪?

启动此程序,main函数对应的线程在调用Leaker之后,应该退出了,后台只有一个Runnable在执行,理论上此时Leaker对象没有任何东西引用,此时应该被GC才对,但是如果使用visualVM查看下内存:

1d34d1511c75d0c79f48e219b1ddfb32.png

即使强制GC之后,此对象依旧存在,说明发生了泄露。

在上面图中的例子使用了一个匿名的Runnable对象,如果将此Runnable改为一个显式声明的对象,如下例子所示:

packagecom.memleak.memleakdemo;public class CauseLeakerNotToLeak implementsRunnable {public voidrun() {while (true)

{

System.out.println("Running... ok");try{

Thread.sleep(1000);

}catch(InterruptedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

LeakerSolved.java

packagecom.memleak.memleakdemo;public classLeakerSolved {

String valueToRead= "Hello world";public voiddoSomething()

{

Thread bgThread= newThread(newCauseLeakerNotToLeak()

);

bgThread.start();

}

}

通过VisualVM则会发现已经不再泄露了:

4980be224365c0d634f749625cc8d376.png

当然,如果使用Java 8带的Lambda表达式:

packagecom.memleak.memleakdemo;public classLeakerLambda {

String valueToRead= "Hello world";public voiddoSomething()

{

Thread bgThread= new Thread(() -> {while(true) {

System.out.println("Running... ok");try{

Thread.sleep(1000);

}catch(InterruptedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}});

bgThread.start();

}

}

也能解决这个问题:

56f3ff5379914d41e1bb0bf70a684908.png

结论:

在创建线程的时候一定要谨慎使用匿名Runnable对象,最好使用命名对象或者Lambda表达式代替。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值