造成OOM(内存溢出)的几种情况
数据库
Cursor没关。
当我们操作完数据库后,一定要调用close()释放资源。构造
Adapter没有使用缓存ContentView。@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vHolder = null;
//如果convertView对象为空则创建新对象,不为空则复用
if (convertView == null) {
convertView = inflater.inflate(..., null);
// 创建 ViewHodler 对象
vHolder = new ViewHolder();
vHolder.img= (ImageView) convertView.findViewById(...);
vHolder.tv= (TextView) convertView
.findViewById(...);
// 将ViewHodler保存到Tag中
convertView.setTag(vHolder);
} else {
//当convertView不为空时,通过getTag()得到View
vHolder = (ViewHolder) convertView.getTag();
}
// 给对象赋值,修改显示的值
vHolder.img.setImageBitmap(...);
vHolder.tv.setText(...);
return convertView;
} static class ViewHolder {
TextView tv;
ImageView img;
}未取消注册广播接收者
registerReceiver()和unregisterReceiver()要成对出现,通常需要在Activity的onDestory()方法去取消注册广播接收者。IO流未关闭 注意用完后及时关闭Bitmap使用后未调用recycle()。Context泄漏 这是一个很隐晦的OutOfMemoryError的情况。先看一个Android官网提供的例子:private static Drawable sBackground;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");
if (sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}这段代码效率很快,但同时又是极其错误的:
我们看一下setBackgroundDrawable(Drawable background)的源码:public void setBackgroundDrawable(Drawable background) {
...
background.setCallback(this);
}有
background.setCallback(this);方法,也就是说Drawable拥有TextView的引用,而TextView又拥有Activity(Context类型)的引用, 因为sBackground为static的,即使Activity被销毁,但是sBackground的生命周期还没走完,所以内存仍然不会被释放。这样就会有内存泄露了。 对,这样想是对的,但是我们看一下setCallback的源码:public final void setCallback(Callback cb) {
mCallback = new WeakReference<Callback>(cb);
}我们会发现里面使用了
WeakReference,所以不会存在内存泄露了,但是官网当时提供的例子明明说有泄露,这是因为在3.0之后, 修复了这个内存泄露的问题,在3.0之前setCallback,方法是没有使用WeakReference的,所以这种泄露的情况在3.0之前会发生,3.0之后已经被修复。线程 线程也是造成内存泄露的一个重要的源头。线程产生内存泄露的主要原因在于线程生命周期的不可控。我们来考虑下面一段代码。
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new MyThread().start();
}
private class MyThread extends Thread{
@Override
public void run() {
super.run();
//耗时的操作
}
}
}假设
MyThread的run函数是一个很费时的操作,当调用finish的时候Activity会销毁掉吗?
事实上由于我们的线程是Activity的内部类,所以MyThread中保存了Activity的一个引用,当MyThread的run函数没有结束时,MyThread是不会被销毁的, 因此它所引用的Activity也不会被销毁,因此就出现了内存泄露的问题。尽量使用
ApplicationContextContext引用的生命周期超过它本身的生命周期,也会导致Context泄漏。 所以如果打算保存一个长时间的对象时尽量使用Application这种Context类型。 例如:mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
改成:
mStorageManager = (StorageManager) getApplicationContext().getSystemService(Context.STORAGE_SERVICE);按道理来说这种系统服务是不会有问题,但是有些厂商在修改的时候,可能会导致
Context无法被及时释放。Handler的使用,在Activity退出的时候注意移除(尤其是循环的时候)
public class ThreadDemo extends Activity {
private static final String TAG = "ThreadDemo";
private int count = 0;
private Handler mHandler = new Handler(); private Runnable mRunnable = new Runnable() { public void run() {
//为了方便 查看,我们用Log打印出来
Log.e(TAG, Thread.currentThread().getName() + " " +count);
//每2秒执行一次
mHandler.postDelayed(mRunnable, 2000);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//通过Handler启动线程
mHandler.post(mRunnable);
}
}这样在也会引发内存泄露。我们应该在
onDestory方法中移除Handler,代码如下:@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(mRunnable);
}
造成OOM(内存溢出)的几种情况的更多相关文章
- Tomcat内存溢出的三种情况及解决办法分析
Tomcat内存溢出的原因 在生产环境中tomcat内存设置不好很容易出现内存溢出.造成内存溢出是不一样的,当然处理方式也不一样. 这里根据平时遇到的情况和相关资料进行一个总结.常见的一般会有下面三种 ...
- Java中OutOfMemoryError(内存溢出)的三种情况及解决办法
转载自:http://blog.sina.com.cn/s/blog_701c951f0100n1sp.html 相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题, ...
- 关于java堆内存溢出的几种情况(转)
[情况一]: java.lang.OutOfMemoryError: Java heap space:这种是java堆内存不够,一个原因是真不够,另一个原因是程序中有死循环: 如果是java堆内存不够 ...
- java中出现内存溢出的几种情况
情况一:java.lang.OutOfMemoryError: Java heap space 原因:java堆内存不足,可能是真的不足,也可能是程序中有死循环 方案:1.调整JVM参数-Xms204 ...
- jvm内存溢出的三种情况以及解决办法
1 前言相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题,这个问题曾困扰了我很长时间,随着解决各类问题经验的积累以及对问题根源的探索,终于有了一个比较深 ...
- [转]JVM内存溢出的几种方式比较
转载自:https://github.com/pzxwhc/MineKnowContainer/issues/25 包括: 1. 栈溢出(StackOverflowError) 2. 堆溢出(OutO ...
- OutOfMemoryError/OOM/内存溢出异常实例分析--虚拟机栈和本地方法栈溢出
关于虚拟机栈和本地方法栈,在JVM规范中描述了两种异常: 1.如果线程请求的栈深度大于JVM所允许的深度,将抛出StackOverflowError异常: 2.如果虚拟机在扩展栈时无法申请到足够的内存 ...
- js内存泄露的几种情况
想解决内存泄露问题,必须知道什么是内存泄露,什么情况下出现内存泄露,才能在遇到问题时,逐个排除.这里只讨论那些不经意间的内存泄露. 一.什么是内存泄露 内存泄露是指一块被分配的内存既不能使用,又不能回 ...
- android加载大量图片内存溢出的三种方法
android加载大量图片内存溢出的三种解决办法 方法一: 在从网络或本地加载图片的时候,只加载缩略图. /** * 按照路径加载图片 * @param path 图片资源的存放路径 * @para ...
随机推荐
- js基础-表单验证和提交
基础知识: 原始提交如下: <form action="/login" method="post" id="form1"> &l ...
- Javascript动画效果(二)
Javascript动画效果(二) 在前面的博客中讲了简单的Javascript动画效果,这篇文章主要介绍我在改变之前代码时发现的一些问题及解决方法. 在前面的多物体宽度变化的例子中,我们给其增加代码 ...
- HT For Web 拓扑图背景设置
HT For Web 的HTML5拓扑图组件graphView背景设置有多种途径可选择: divBackground:通过css设置graphView对应的div背景 Painter:通过graphV ...
- WCF实现方法重载
一.服务契约(包括回调契约)通过指定不同的OperationContract.Name来实现重载方法,当然代码部份还是必需符合C#的重载要求,即相同方法名称,不同的参数个数或参数类型 namespac ...
- 解决:HTML中多文本域(textarea)回车后数据存入数据库,EL表达式取出异常。
问题描述: 当多文本域(textarea)回车后数据存入数据库. EL表达式取出异常,值换行倒置页面报错. 问题解决: 存值脚本代码,提交前转换\n为<br/>. <script t ...
- 模块化利器: 一篇文章掌握RequireJS常用知识
通过本文,你可以对模块化开发和AMD规范有一个较直观的认识,并详细地学习RequireJS这个模块化开发工具的常见用法.本文采取循序渐进的方式,从理论到实践,从RequireJS官方API文档中,总结 ...
- Socket开发框架之数据加密及完整性检查
在前面两篇介绍了Socket框架的设计思路以及数据传输方面的内容,整个框架的设计指导原则就是易于使用及安全性较好,可以用来从客户端到服务端的数据安全传输,那么实现这个目标就需要设计好消息的传输和数据加 ...
- 基于C#的MongoDB数据库开发应用(1)--MongoDB数据库的基础知识和使用
在花了不少时间研究学习了MongoDB数据库的相关知识,以及利用C#对MongoDB数据库的封装.测试应用后,决定花一些时间来总结一下最近的研究心得,把这个数据库的应用单独作为一个系列来介绍,希望从各 ...
- 【C#】分享一个可灵活设置边框的Panel
---------------------------更新:2014-05-19--------------------------- 优化了一下逻辑,就是既然可以通过设置BorderSide=Non ...
- QT添加二次确认功能,QMessageBox的使用
对于一些重要的操作需要让用户再次确认一次,给出几个基本的实例 是和否 switch( QMessageBox::warning(NULL, "warning",QString::f ...