`
Jacular
  • 浏览: 182745 次
  • 性别: Icon_minigender_1
  • 来自: 云南
社区版块
存档分类
最新评论

Android防止内存溢出浅析

 
阅读更多
Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M。但是Android采用的是Java语言编写,所以在很大程度上,Android的内存机制等同于Java的内存机制,在刚开始开发的时候,内存的限制问题会给我们带来内存溢出等严重问题。在我们不使用一些内存的时候,我们要尽量在Android或者其他平台上避免在运行其他程序时,保存必要的状态,使得一些死进程所带来的内存问题,应该尽量在关闭程序或者保存状态的时候释放掉,这样能提高系统在运行方面的流畅性。



Android的内存主要表现在:

1. 在Android平台上,长期保持一些资源的引用,造成一些内存不能释放,带来的内存泄露问题很多。比如:Context(下文中提到的Activity都是Context),在一些你需要保持你的首个类对象状态,并且把状态传入其他类对象中时,这样消除掉首个类对象之前,你必须先把接收类对象释放掉。需要注意一点的是:因为在Java或者Android内存机制中,顶点的结点释放前必须保证其他对象没有调用才能被系统GC回收释放。我们来看一段代码:

 

@Override 

protected void onCreate(Bundle state) { 

      super.onCreate(state); 

      TextViewlabel = new TextView(this); 

      label.setText("Leaksare bad"); 

      setContentView(label); 








这个代码的意思就是我们把一个TextView的实例加载到了我们正在运行的Activity(Context)当中,因此,通过GC回收机制,我们知道,要释放Context,就必须先释放掉引用他的一些对象。如果没有,那在要释放Context的时候,你会发现会有大量的内存溢出。所以在你不小心的情况下内存溢出是一件非常容易的事情。 保存一些对象时,同时也会造成内存泄露。最简单的比如说位图(Bitmap),比如说:在屏幕旋转时,会破坏当前保持的一个Activity状态,并且重新申请生成新的Activity,直到新的Activity状态被保存。我们再看一段代码:

 

privatestatic 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); 








这个代码是非常快的同时也是错误的。它的内存泄露很容易出在屏幕转移的方向上。虽然我们会发现没有显示的保存Context这个实例,但是当我们把绘制的图连接到一个视图的时候,Drawable就会将被View设置为回调,这就说明,在上述的代码中,其实在绘制TextView到活动中的时候,我们已经引用到了这个Activity。链接情况可以表现为:Drawable->TextView->Context。

所以在想要释放Context的时候,其实还是保存在内存中,并没有得到释放。

如何避免这种情况:主要在于。线程最容易出错。大家不要小看线程,在Android里面线程最容易造成内存泄露。线程产生内存泄露的主要原因在于线程生命周期的不可控。下面有一段代码:

 

publicclass MyTest extends Activity { 

     @Override 

     publicvoid onCreate(BundlesavedInstanceState) { 

         super.onCreate(savedInstanceState); 

         setContentView(R.layout.main); 

         new MyThread().start(); 

     } 

   

     privateclass MyThread extends Thread{ 

         @Override 

         public void run() { 

            super.run(); 

            //do somthing 

         } 

     } 





代码很简单,但是在Android上又来新问题了,当我们在切换视图屏幕的时候(横竖屏),就会重新建立横屏或者竖屏的Activity。我们形象的认为之前建立的Activity会被回收,但是事实如何呢?Java机制不会给你同样的感受,在我们释放Activity之前,因为run函数没有结束,这样MyThread并没有销毁,因此引用它的Activity(Mytest)也有没有被销毁,因此也带来的内存泄露问题。

有些人喜欢用Android提供的AsyncTask,但事实上AsyncTask的问题更加严重,Thread只有在run函数不结束时才出现这种内存泄露问题,然而AsyncTask内部的实现机制是运用了ThreadPoolExcutor,该类产生的Thread对象的生命周期是不确定的,是应用程序无法控制的,因此如果AsyncTask作为Activity的内部类,就更容易出现内存泄露的问题。

线程问题的改进方式主要有:

l  将线程的内部类,改为静态内部类。

l  在程序中尽量采用弱引用保存Context。



2. 万恶的bitmap。。。

Bitmap是一个很万恶的对象,对于一个内存对象,如果该对象所占内存过大,在超出了系统的内存限制时候,内存泄露问题就很明显了。。

解决bitmap主要是要解决在内存尽量不保存它或者使得采样率变小。在很多场合下,因为我们的图片像素很高,而对于手机屏幕尺寸来说我们并不用那么高像素比例的图片来加载时,我们就可以先把图片的采样率降低在做原来的UI操作。

如果在我们不需要保存bitmap对象的引用时候,我们还可以用软引用来做替换。具体的实例代码google上面也有很多。



综上所述,要避免内存泄露,主要要遵循以下几点:

第一:不要为Context长期保存引用(要引用Context就要使得引用对象和它本身的生命周期保持一致)。

第二:如果要使用到Context,尽量使用ApplicationContext去代替Context,因为ApplicationContext的生命周期较长,引用情况下不会造成内存泄露问题

第三:在你不控制对象的生命周期的情况下避免在你的Activity中使用static变量。尽量使用WeakReference去代替一个static。

第四:垃圾回收器并不保证能准确回收内存,这样在使用自己需要的内容时,主要生命周期和及时释放掉不需要的对象。尽量在Activity的生命周期结束时,在onDestroy中把我们做引用的其他对象做释放,比如:cursor.close()。



其实我们可以在很多方面使用更少的代码去完成程序。比如:我们可以多的使用9patch图片等。有很多细节地方都可以值得我们去发现、挖掘更多的内存问题。我们要是能做到C/C++对于程序的“谁创建,谁释放”原则,那我们对于内存的把握,并不比Java或Android本身的GC机制差,而且更好的控制内存,能使我们的手机运行得更流畅。

分享到:
评论

相关推荐

    Android防止内存溢出浅析.zip

    以下是对Android防止内存溢出的深入浅析: 1. **Android内存管理机制** - **Dalvik/ART虚拟机**:Android系统使用Dalvik或ART虚拟机执行应用程序,它们都有自己的内存管理策略。 - **堆内存**:Java对象主要存储...

    基于Android防止内存溢出浅析

    理解并正确处理Android组件(如Activity、Service)的生命周期是防止内存溢出的关键。当组件不再使用时,应及时释放资源,如关闭数据库连接,停止正在执行的后台任务,解除对其他对象的引用。 **使用WeakReference...

    Android应用源码之防止内存溢出浅析.zip项目安卓应用源码下载

    Android应用源码之防止内存溢出浅析.zip项目安卓应用源码下载Android应用源码之防止内存溢出浅析.zip项目安卓应用源码下载 1.适合学生毕业设计研究参考 2.适合个人学习研究参考 3.适合公司开发项目技术参考

    安卓Android源码——防止内存溢出浅析.zip

    本资料"安卓Android源码——防止内存溢出浅析"将深入探讨如何在Android源码层面理解和预防内存溢出。 首先,了解Android内存结构是必要的。Android内存分为堆内存和栈内存,Java对象主要存储在堆中,而局部变量和...

    防止内存溢出浅析

    7. **优化代码结构**:良好的编程习惯和设计模式有助于防止内存溢出。例如,遵循单一职责原则,避免循环引用,及时释放资源,使用Parcelable而非Serializable等。 8. **系统级别的优化**:了解Android系统的内存...

    Android应用源码之防止内存溢出浅析.zip

    本资料"Android应用源码之防止内存溢出浅析"正是针对这一问题提供了解决方案。下面,我们将深入探讨Android应用中内存溢出的原因、检测以及如何通过优化源码来避免。 1. 内存溢出原因: - 大量对象创建:短时间内...

    Android应用源码之防止内存溢出浅析-IT计算机-毕业设计.zip

    这个"Android应用源码之防止内存溢出浅析"的压缩包可能包含了示例代码,通过阅读和分析这些代码,你可以理解以上策略如何在实际项目中应用。例如,查看图片加载部分,是否使用了合适的解码选项;检查Activity的生命...

    应用源码之防止内存溢出浅析.zip

    本资料"应用源码之防止内存溢出浅析"旨在深入探讨Android应用中的内存优化,帮助开发者避免因不当使用内存导致的应用崩溃。以下是根据标题、描述和标签提炼的相关知识点: 1. **Java内存模型**:Java内存分为堆内存...

    安卓开发-防止内存溢出浅析.zip

    本篇将深入探讨如何防止安卓应用中的内存溢出,从内存泄漏、大对象分配、Bitmap处理等方面进行详细解析。 一、理解安卓内存管理机制 安卓系统采用Dalvik/ART虚拟机,基于垃圾收集(Garbage Collection,GC)的内存...

    Android编程内存溢出与防范方法浅析

    在Android编程中,内存溢出(Memory Leak)是一个常见的问题,尤其对于有限的移动设备资源而言,内存管理显得尤为重要。Android的Dalvik虚拟机虽然在内存管理上与Java虚拟机有相似之处,但由于其内存限制(通常是16...

    android源码包集合4

    zz-doctor中医大夫助理...防止内存溢出浅析.rar 飞行历 飞行模式 AirPlus.rar 飞行射击类游戏源码.rar 高仿 WIN8系统 磁贴点击下沉倾斜效果源码.zip 高仿基于android2.2(Froyo)的Contacts.zip 高仿多米音乐播放器.rar

    浅析安卓(Android)的性能优化

    3. 使用Bitmap时注意内存控制:Bitmap对象占用了大量内存,我们需要合理地加载、解码和复用Bitmap,使用BitmapFactory.Options来控制解码时的大小,避免一次性加载过大图像导致内存溢出。 4. 利用Android提供的内存...

    浅析KJFrameForAndroid框架如何高效加载Bitmap

    然而,由于内存限制,直接加载大尺寸的Bitmap可能导致内存溢出(OOM)异常,因此高效地加载和管理Bitmap至关重要。KJFrameForAndroid是一个开源的Android应用开发框架,它提供了一种优化的Bitmap加载策略来避免此类...

Global site tag (gtag.js) - Google Analytics