这几天与在某群与群友讨论了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. PTA 统计二叉树度为2的结点个数

    6-4 统计二叉树度为2的结点个数 (11 分)   本题要求实现一个函数,可统计二叉树中度为2的结点个数. 函数接口定义: int NodeCount ( BiTree T); T是二叉树树根指针, ...

  2. UML第二部分和创建型模式

    状态机视图通过对每个类的对象的生命期进行建模 描述了对象时间上的动态行为 .状态指就某个特定类而言 对于发生的事件具有相同性质响应的一系列对象值.状态机不但可以描述类的行为 而且可以描述用例 协作和方 ...

  3. Spring笔记(五)

    Spring 事务操作 一.事务(概念) 1. 什么是事务 事务是数据库的最基本单元,逻辑上的一组操作,要么都成功,如果有一个失败,那么所有的操作都失败 典型场景: lucy转账100元给mary l ...

  4. 利用Vue实现一个简单的购物车功能

    开始学习Vue的小白,dalao多多指正 想要实现下面这个界面,包含总价计算.数量增加和移除功能 话不多说代码如下 <!DOCTYPE html> <html> <hea ...

  5. Python中切片的应用

    Python中切片的应用 Python中可以通过切片实现对列表或者字符串取指定范围的操作,实际就是通过对列表或者字符串通过索引进行操作. 具体细节点击廖雪峰Python教程,其中的课后小问题在此记录下 ...

  6. python基础(六):列表的使用(下)

    列表排序的三种方式 sort()方法:原地修改列表的排序方法 注 1:" 默认是升序" ,参数 reverse=True,表示将列表降序. 注 2:" 原地修改列表&qu ...

  7. 【剑指offer】10:矩形覆盖

    题目描述: 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 解题思路: ①方法一 对于这种题没有思路怎么办?可以先从最 ...

  8. 【macOS】屏蔽Big Sur更新提示 消除更新红点

    下面介绍如何屏蔽macOS系统更新,屏蔽Big Sur更新提示,消除更新红点. 取消自动更新选项 请选取苹果菜单  > "系统偏好设置",然后点按"软件更新&qu ...

  9. Manjaro 蓝牙连接问题

    1 问题描述 蓝牙不能连接,或者连接上了没有声音. 2 解决方案 首先确保相应软件包存在: sudo pacman -S bluez bluez-utils pulseaudio-bluetooth ...

  10. Tomcat集群 Nginx负载均衡 shell脚本实时监控Nginx

    第一步,安装Tomcat 系统环境:Centos7 第1步:下载tomcat安装包 tomcat官网:https://tomcat.apache.org/ 第2步:安装包上传至linux中 第3步:下 ...