内存抖动
OOM
已经分配的内存+准备分配的内存 >= 内存的总大小,就会出现OOM
java.long.OutOfMemoryError
:申请内存时,没有足够的内存空间可配分,就会报此异常
可能会出现OOM的情况:
Java堆内存溢出
无足够连续的内存空间
FD(文件)数量超出限制:最大限制1024
线程数量超出限制:最大限制1024
虚拟内存不足
内存泄漏
指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏危害可以忽略,但内存泄漏堆积后果很严重,无论多少内存,迟早会被占光
常见的内存泄漏如下:
单例造成的内存泄漏
//单例模式
单例模式在我们项目中经常会用到,比如,我们项目中使用ActivityManager单例,获取这个单例需要传入context对象。代码如下:
public class ActivityManager {
private static final String TAG = "ActivityManager";
private Context context;
private static ActivityManager instance;
private ActivityManager(Context context) {
this.context = context;
}
public static ActivityManager getInstance(Context context) {
if (instance == null) {
instance = new ActivityManager(context);
}
return instance;
}
}
上面代码,在构造方法里传入context,如果不加注意,很容易因为生命周期的长短而引起内存泄漏。注意请在这里传入Application的context而不是Activity的context,因为如果传入的是Activity的context,当Activity退出时,此context并不会被回收,因为单例对象持有该context的引用,从而引起内存泄漏。如果传入的是Application的context,便不会引发内存泄漏,因为context的生命周期和Application一样长,所以正确的单例写法如下:
public class ActivityManager {
private static final String TAG = "ActivityManager";
private Context context;
private static ActivityManager instance;
private ActivityManager(Context context) {
this.context = context.getApplicationContext();
}
public static ActivityManager getInstance(Context context) {
if (instance == null) {
instance = new ActivityManager(context);
}
return instance;
}
}
非静态内部类创建静态实例造成的内存泄漏
非静态内部类(包括匿名内部类)默认就会持有外部类的引用,当非静态内部类对象的生命周期比外部类对象的生命周期长时,就会导致内存泄露。
public class TestLeakActivity extends Activity {
private static TestResource mResource = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_leak);
if (mResource == null){
mResource = new TestResource();
}
}
private class TestResource{
}
}
解决方案
可以将非静态内部类改成静态内部类
private static class TestResource{
}
Handler造成的内存泄漏
往期有讲到,链接如下:
Handler面试知识点
线程造成的内存泄漏
也是把内部类改成静态内部类就解决了
WebView造成的内存泄漏
解决方案:
单独放在一个进程去使用,Activity销毁的时候直接在onDestory()直接android.os.Process.killProcess(android.os.Process.myPid)
销毁进程
资源对象未关闭导致
对于资源若在 Activity 销毁时无及时关闭 / 注销这些资源,则这些资源将不会被回收,从而造成内存泄漏。
如广播、文件、Bitmap、数据库、EventBus等使用
Glide 内存泄漏的原因
Glide内存泄漏的主要原因是未正确释放加载的图片资源。当我们使用Glide加载图片时,它会将图片缓存再内存中,以便下次快速加载。然而,当我们不再需要这些图片时,如果没有正确释放,就会导致内存泄漏。
下面是一个使用Glide加载图片的示例代码:
Glide.with(context)
.load(imageUrl)
.into(imageView);
在这个示例中吗,我们使用Glide.with(context)
开始一个Glide请求,并使用.load(imageUrl)
加载图片。最后,使用`.into(imageView)将图片显示再ImageView中。
然而,这段代码存在一个潜在的内存泄漏问题。当Activity或Fragment销毁时,如果Glide请求还未完成,就会导致内存泄漏。
解决方案
为了避免Glide内存泄漏,我峨嵋你选用哟在合适的时机取消Glide请求。一般来说,我们可以在Activity或Fragment的生命周期方法取消Glide请求。
下面是一个示例代码,在Activity的onStop()
方法中取消Glide请求:
protected void onStop() {
super.onStop();
Glide.with(context).pauseRequests();
}
@Override
protected void onStart() {
super.onStart();
Glide.with(context).resumeRequests();
}
在这个示例中,我们在onStop()
方法中调用Glide.with(context).pauseRequests()
,这样可以暂停Glide请求。而在onStart()
,方法中调用Glide.with(context).resumeRequests()
,这样可以恢复Glide请求
分析内存泄漏的工具
leakcanary
内存溢出
指程序在申请内存时,没有足够的内存空间共其使用,出现out of memory。