这几天与在某群与群友讨论了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. day03---Vue(04)

    一.组件 组件(Component)是 Vue.js 最强大的功能之一. 组件可以扩展 HTML 元素,封装可重用的代码. 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界 ...

  2. golang 性能优化分析:benchmark 结合 pprof

    前面 2 篇 golang 性能优化分析系列文章: golang 性能优化分析工具 pprof (上) golang 性能优化分析工具 pprof (下) 一.基准测试 benchmark 简介 在 ...

  3. ASP.NET Core依赖注入初识与思考

    文章首发地址 一.前言 在上一篇中,我们讲述了什么是控制反转(IoC)以及通过哪些方式实现的.这其中,我们明白了,控制反转(IoC) 是一种软件设计的模式,指导我们设计出更优良,更具有松耦合的程序,而 ...

  4. Dynamics CRM安装教程一:域环境准备

    服务器环境:Windows Service 2016 Stand Windows域是计算机网络的一种形式,其中所有用户账户,计算机,打印机和其他安全主体都在位于称为域控制器的一个或多个中央计算机集群上 ...

  5. (十四)docker exec 详解

    1. 作用 在运行的容器中执行命令 2. 语法 docker exec [OPTIONS] CONTAINER COMMAND [ARG...] OPTIONS说明: -d :分离模式: 在后台运行 ...

  6. linux 在某个路径下,查找某个文件

    find /cephfs/netdisk/ -name "*.sql"

  7. 简单的了解下Java设计模式:迭代器模式(转载)

    迭代器模式定义 迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示. Java 开发过程中遍历是常用的.如下边程序: for(int i =0 ; ...

  8. 介绍一款能取代 Scrapy 的 Python 爬虫框架 - feapder

    1. 前言 大家好,我是安果! 众所周知,Python 最流行的爬虫框架是 Scrapy,它主要用于爬取网站结构性数据 今天推荐一款更加简单.轻量级,且功能强大的爬虫框架:feapder 项目地址: ...

  9. 数栈运维实例:Oracle数据库运维场景下,智能运维如何落地生根?

    从马车到汽车是为了提升运输效率,而随着时代的发展,如今我们又希望用自动驾驶把驾驶员从开车这项体力劳动中解放出来,增加运行效率,同时也可减少交通事故发生率,这也是企业对于智能运维的诉求. 从人工运维到自 ...

  10. MySQL查询日志介绍

    MySQL查询日志介绍 MySQL的查询日志记录了所有MySQL数据库请求的信息.无论这些请求是否得到了正确的执行.默认文件名为hostname.log.默认情况下MySQL查询日志是关闭的.生产环境 ...