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

示例代码如下:

package com.memleak.memleakdemo;

public class Leaker {

    String valueToRead = "Hello world";

    public void doSomething()
{
Thread bgThread = new Thread(
new Runnable()
{ public void run() {
while (true)
{
System.out.println("Running... ok");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} }
);
bgThread.start();
} }

Main函数:

package com.memleak.memleakdemo;

/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
Leaker l = new Leaker();
l.doSomething();
}
}

问题出在哪?

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

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

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

package com.memleak.memleakdemo;

public class CauseLeakerNotToLeak implements Runnable {

    public void run() {
while (true)
{
System.out.println("Running... ok");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} }
LeakerSolved.java
package com.memleak.memleakdemo;

public class LeakerSolved {

    String valueToRead = "Hello world";

    public void doSomething()
{
Thread bgThread = new Thread(
new CauseLeakerNotToLeak()
);
bgThread.start();
} }

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

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

package com.memleak.memleakdemo;

public class LeakerLambda {

    String valueToRead = "Hello world";

    public void doSomething()
{
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();
} }

也能解决这个问题:

结论:

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

Java匿名对象导致的内存泄漏的更多相关文章

  1. 解决java.beans.Introspector导致的内存泄漏

    解决方案: 在WEB.XML 中配置监听器: <listener> <listener-class> org.springframework.web.util.Introspe ...

  2. 在Activity中使用Thread导致的内存泄漏

    https://github.com/bboyfeiyu/android-tech-frontier/tree/master/issue-7/%E5%9C%A8Activity%E4%B8%AD%E4 ...

  3. 精华阅读第 13 期 |常见的八种导致 APP 内存泄漏的问题

    本期是移动开发精英俱乐部的第13期文章,都是以技术为主,所以这里就不过多的进行赘述了,我们直接看干货内容吧!本文系ITOM管理平台OneAPM整理. 实际项目中的MVVM(积木)模式–序章 导读:开篇 ...

  4. static关键字所导致的内存泄漏问题

    大家都知道内存泄漏和内存溢出是不一样的,内存泄漏所导致的越来越多的内存得不到回收的失手,最终就有可能导致内存溢出,下面说一下使用staitc属性所导致的内存泄漏的问题. 在dalvik虚拟机中,sta ...

  5. 使用block的时候,导致的内存泄漏

    明确,只要在block里边用到我们自己的东西,成员变量,self之类的,我们都需要将其拿出来,把它做成弱指针以便之后进行释放. 在ZPShareViewController这个控制器中,由如下代码: ...

  6. 一个驱动导致的内存泄漏问题的分析过程(meminfo->pmap->slabtop->alloc_calls)

    关键词:sqllite.meminfo.slabinfo.alloc_calls.nand.SUnreclaim等等. 下面记录一个由于驱动导致的内存泄漏问题分析过程. 首先介绍问题背景,在一款嵌入式 ...

  7. vue自定义指令导致的内存泄漏问题解决

    vue的自定义指令是一个比较容易引起内存泄漏的地方,原因就在于指令通常给元素绑定了事件,但是如果忘记了解绑,就会产生内存泄漏的问题. 看下面代码: directives: { scroll: { in ...

  8. 使用HandyJSON导致的内存泄漏问题相关解决方法

    在移动开发中,与服务器打交道是不可避免的,从服务器拿到的接口数据最终都会被我们解析成模型,现在比较常见的数据传输格式是json格式,对json格式的解析可以使用原生的解析方式,也可以使用第三方的,我们 ...

  9. Java匿名对象介绍

    Java匿名对象介绍 什么是匿名对象? 顾名思义就是没有变量名的对象,即创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量. 匿名对象命名格式:以Scanner类举例 new Scann ...

随机推荐

  1. Android Studio 之 EditText

    EditText 简介 •简介 EditText是一个非常重要的组件,可以说它是用户和Android应用进行数据传输窗户: 有了它就等于有了一扇和Android应用传输的门,通过它用户可以把数据传给A ...

  2. Oment++ 初学者教程 第4节-将其转变为真实网络

    4.1两个以上的节点 现在,我们将迈出一大步:创建几个tic模块并将它们连接到网络中.现在,我们将使它们的工作变得简单:一个节点生成一条消息,其他节点继续沿随机方向扔消息,直到它到达预定的目标节点为止 ...

  3. shell分支与循环结构

    1. 条件选择 1.1 条件判断分支介绍 格式 if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMM ...

  4. 【10.5NOIP普及模拟】sum

    [10.5NOIP普及模拟]sum 文章目录 [10.5NOIP普及模拟]sum 题目描述 输入 输出 输入输出样例 样例输入 样例输出 解析 code 题目描述 小x有很多糖果,分成了 N 堆,排成 ...

  5. RocketMq(一)初识

    消息中间件基本上是互联网公司必用的一个中间件,为什么要使用MQ,当然是因为能给我们的系统带来很多好处. 消息队列简单来说是一种先进先出的数据结构,先简单认识下. 一.应用场景 消息中间件主要应用场景主 ...

  6. linux下更新gcc

    1 下载源码 链接 目前最新为9.2版本. 2 解压 tar -zxvf gcc-9.2.0.tar.gz cd gcc-9.2.0 3 download_prerequisites脚本 运行这个脚本 ...

  7. Day16_94_IO_循环读取文件字节流read()方法(二)

    循环读取文件字节流read()方法 通过read()循环读取数据,但是read()每次都只能读取一个字节,频繁读取磁盘对磁盘有伤害,且效率低. import java.io.FileInputStre ...

  8. Webpack的理解以及解决了的问题

    一.背景 Webpack 最初的目标是实现前端项目的模块化,旨在更高效地管理和维护项目中的每一个资源 模块化 最早的时候,我们会通过文件划分的形式实现模块化,也就是将每个功能及其相关状态数据各自单独放 ...

  9. POJ1486模拟或者匈牙利变种

    题意:       有n个矩形,每个矩形上的某个位置上都有一个点,但是由于矩形是透明的,当一些矩形重叠在一起的时候就很可能分不清哪个点是那个矩形的,给你n个矩形的坐标,还有n个点的坐标,然后让你找出所 ...

  10. 使用同步或异步的方式完成 I/O 访问和操作(Windows核心编程)

    0x01 Windows 中对文件的底层操作 Windows 为了方便开发人员操作 I/O 设备(这些设备包括套接字.管道.文件.串口.目录等),对这些设备的差异进行了隐藏,所以开发人员在使用这些设备 ...