内存泄漏和内存溢出以及原因和解决方案
1.什么是内存泄漏?
Java 中的内存泄漏是指应用程序不再需要的对象在 Java 虚拟机 (JVM) 中仍然存在的状态。通俗来讲就是生命周期长的对象持有生命周期短的对象,导致GC无法回收本该需要回收的对象。
2.造成内存泄露的原因有哪些?
(1)非静态内部类造成的内存泄漏
那么为什么非静态内部类会造成内存泄漏呢?
看个例子
public class Outer {private String TAG="Outer";private Runnable runnable = new Runnable(){public void run(){System.out.println("inner run: " + TAG);}};
}
通过javac Outer.java 我们得到两个class文件
Outer.class
public class Outer {private String TAG = "Outer";private Runnable runnable = new Runnable() {public void run() {System.out.println("inner run: " + Outer.this.TAG);}};public Outer() {}
}
Outer$1.class
class Outer$1 implements Runnable {Outer$1(Outer var1) {this.this$0 = var1;}public void run() {System.out.println("inner run: " + this.this$0.TAG);}
}
看到没有,在Outer$1.class中,Outer$1是Runnable,我们可以看到在Outer$1类函数中,传了外部类Outer对象,this.this$0是指向Outer对象。Outer$1持有Outer,也就是Runnable持有Outer。
结论:非静态内部类持有外部类的引用
看下静态内部类:
public class Outer {private static String TAG="Outer";private static Runnable runnable = new Runnable(){public void run(){System.out.println("inner run: " + TAG);}};
}
通过javac Outer.java命令
我们看到Outer$1.class
class Outer$1 implements Runnable {Outer$1() {}public void run() {System.out.println("inner run: " + Outer.TAG);}
}
我们可以得到Outer$1并没有Outer,所以静态内部类不持有外部类。
解决方案:使用静态内部类替换内部类解决非静态内部类造成的内存泄漏。
(2)单例造成的内存泄漏
public class SingleInstance {private Context context;private static SingleInstance instance;private SingleInstance(Context context) {this.context = context.getApplicationContext();}public static SingleInstance getInstance(Context context) {if (instance == null) {synchronized (SingleInstance.class) {if (instance == null) {instance = new SingleInstance(context);}}}return instance;}}
如果 SingleInstance.getInstance(context)传入的是Activity的context,那么该Activity就会被单例对象所持有,他的生命周期等于整个应用程序的生命周期,当Activity退出了就不会被回收,造成了内存泄漏。
如果传入的是 Application 的 Context,因为 Application 的生命周期就是整个应用的生命周期,这样是没有问题的。
(3)Handler造成的内存泄漏
1.匿名内部类:
Handler handler=new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);}
};
2.非静态内部类(同上面的非静态内部类造成的内存泄漏)
protected class AppHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {}}}
解决方案:静态内部类+弱引用
private static class MyHandler extends Handler {WeakReference<Activity> activity;MyHandler(Activity activity){this.activity=new WeakReference<Activity>(activity);}public void handleMessage(Message message){switch (message.what){}}}
当Activity销毁的时
// 清空消息队列,移除对外部类的引用@Overrideprotected void onDestroy() {super.onDestroy();mHandler.removeCallbacksAndMessages(null);}
(4)资源对象使用后未及时关闭
广播BraodcastReceiver
、文件流Fire
、图片资源Bitmap
、数据库游标
等在Activity/Fragment的onDestory方法内要关闭掉。
3、内存泄漏的危害
1.一次的内存泄漏可能看不出来什么影响,但是较多的内存泄漏会造成应用卡顿。因为系统分配给每个应用的内存是有限的,内存泄漏会导致其他组件的可用内存变少,一方面系统GC频率变高,GC时所有进程都会等待,会造成系统变卡顿。另一方面内存变少,可能使得系统额外分配给该对象一些内存,而影响整个系统的运行情况。
2、导致程序运行崩溃(OOM):一旦内存不足以为某些对象分配所需要的空间,将会导致程序崩溃,造成体验进一步变差。
4.如何来检测内存溢出的情况呢?
见上一篇文章:leakCanary检测内存泄漏的原理(持续更新)_程序猿yz的博客-CSDN博客_leakcanary
本文参考了:为啥非静态内部类能持有外部类? - 腾讯云开发者社区-腾讯云
内存泄漏和内存溢出以及原因和解决方案相关推荐
- 内存溢出和内存泄漏的区别、产生原因以及解决方案
内存溢出和内存泄漏的区别.产生原因以及解决方案 参考文章: (1)内存溢出和内存泄漏的区别.产生原因以及解决方案 (2)https://www.cnblogs.com/ziyoublog/p/1038 ...
- 内存溢出和内存泄漏的区别、产生原因以及解决方案 转
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory:比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出. ...
- 内存溢出和内存泄漏的区别,产生原因以及解决方案
一.概念与区别 内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory:比如申请了一个integer,但给它存了long才能存下的数,那 ...
- python会不会出现内存泄露_Python内存泄漏和内存溢出的解决方案
一.内存泄漏 像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题. 对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是 ...
- 内存泄漏和内存溢出的关系和区别
作者:不怕天黑_0819 链接:https://www.jianshu.com/p/61d34df7eabe 一.内存泄漏(memory leak) 1.内存泄漏是指程序中已动态分配的堆内存由于某种原 ...
- java 内存溢出 内存泄露_JVM——内存泄漏与内存溢出
1.内存溢出 1.1 什么是Java的内存溢出? 在Java程序运行的过程中,经常会碰到以下错误:java.lang.OutOfMemoryError. 通俗讲,内存溢出是指程序在申请内存时,没有足够 ...
- 段错误、内存泄漏、内存溢出、堆溢出、栈溢出
参考:内存泄漏.内存溢出.段错误.堆溢出.栈溢出 作者:焦木白 发布时间:2019-10-22 网址:https://blog.csdn.net/jiaomubai/article/details/1 ...
- java内存泄漏和内存溢出_Java和内存泄漏
java内存泄漏和内存溢出 总览 术语"内存泄漏"在Java中的使用方式不同于在其他语言中使用的方式. 通用术语中的"内存泄漏"是什么意思,在Java中如何使用 ...
- python会内存泄漏吗_Python内存泄漏和内存溢出的解决方法
Python内存泄漏和内存溢出的解决方法 发布时间:2020-10-30 23:08:34 来源:亿速云 阅读:92 作者:Leah 这篇文章将为大家详细讲解有关Python内存泄漏和内存溢出的解决方 ...
- python 内存溢出能捕获吗_Python内存泄漏和内存溢出的解决方案
一.内存泄漏 像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题. 对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是 ...
最新文章
- 4D毫米波雷达Radar
- 加码 2000 亿还不够,阿里云再建三座超级数据中心加速新基建
- VS2013无法启动IIS Express Web的解决办法
- Vue 第一天学习 ---2018.06.28
- PAT1052 卖个萌 (20 分)【别人的代码 借鉴从字符串中截取特定部分的思路】
- Mapgis6.7 林相图自动注记 .
- Java面试题 20在面向对象编程里,经常使用is-a来说明对象之间的继承关系
- 查询错误_三菱PLC快捷查询错误代码(全)
- react循环key值_01 React快速入门(一)——使用循环时对于‘key’报错处理
- libsvm 参数以及计算测试点相似度
- 服务器系列和酷睿系列,三大系列 从英特尔主流处理器选择服务器(2)
- SQLyog——下载2058问题
- ArcGIS符号库下载 | 制图规范、三调、1:1万地形图、土地利用总体规划图.....
- 一种标准地图服务转矢量Shapefile方法
- Android教父高焕堂谈Android“开源”与“兼容”
- 对比只适用于有两个或多于两个层次的因子
- 关注智能眼镜:tooz Devkit 20
- JSP环境的搭建及程序初步
- Android 之 APP上架应用宝平台
- gcc常用命令与gcc编译器背后的故事
热门文章
- android字体有些显示不正常显示,为什么iconfont字体图标在安卓机上显示不出来
- C语言自定义类型详解!
- 一起来创建一个无向图吧!
- 从一个ELF程序的加载窥探操作系统内核-(5)
- EasyPlayer播放H.265视频,播放器快照时间显示的问题优化
- android RadioGroup位置,android RadioGroup
- 一本通与众不同_是什么使电子商务设计与众不同?
- linux服务器状态查看命令,Linux服务器操作系统查看命令
- Win10 端口被占用解决方案
- iptables 打开端口_如何在iptables中打开端口?