`

Android,谁动了我的内存(转)

阅读更多

一、 Android的内存机制

    Android的程序由Java语言编写,所以Android的内存管理与Java的内存管理相似。程序员通过new为对象分配内存,所有对象在java堆内分配空间;然而对象的释放是由垃圾回收器来完成的。C/C++中的内存机制是“谁污染,谁治理”,java的就比较人性化了,给我们请了一个专门的清洁工(GC)。

    那么GC怎么能够确认某一个对象是不是已经被废弃了呢?Java采用了有向图的原理。Java将引用关系考虑为图的有向边,有向边从引用者指向引用对象。线程对象可以作为有向图的起始顶点,该图就是从起始顶点开始的一棵树,根顶点可以到达的对象都是有效对象,GC不会回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC回收。

二、Android的内存溢出

    Android的内存溢出是如何发生的?

    Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M,有的机器为24M。因此我们所能利用的内存空间是有限的。如果我们的内存占用超过了一定的水平就会出现OutOfMemory的错误。

为什么会出现内存不够用的情况呢?我想原因主要有两个:

  • 由于我们程序的失误,长期保持某些资源(如Context)的引用,造成内存泄露,资源造成得不到释放。
  • 保存了多个耗用内存过大的对象(如Bitmap),造成内存超出限制。

三、万恶的static

    static是Java中的一个关键字,当用它来修饰成员变量时,那么该变量就属于该类,而不是该类的实例。所以用static修饰的变量,它的生命周期是很长的,如果用它来引用一些资源耗费过多的实例(Context的情况最多),这时就要谨慎对待了。

 

  1. public class ClassName {  
  2.      private static Context mContext;  
  3.      //省略  
  4. }  

 

以上的代码是很危险的,如果将Activity赋值到么mContext的话。那么即使该Activity已经onDestroy,但是由于仍有对象保存它的引用,因此该Activity依然不会被释放。

    我们举Android文档中的一个例子。

  1. private   static  Drawable sBackground;  
  2.      
  3.  @Override   
  4.  protected   void  onCreate(Bundle state) {  
  5.    super .onCreate(state);  
  6.      
  7.    TextView label = new  TextView( this );  
  8.    label.setText("Leaks are bad" );  
  9.      
  10.    if  (sBackground ==  null ) {  
  11.      sBackground = getDrawable(R.drawable.large_bitmap);  
  12.    }  
  13.    label.setBackgroundDrawable(sBackground);  
  14.      
  15.    setContentView(label);  
  16.  }  

     sBackground, 是一个静态的变量,但是我们发现,我们并没有显式的保存Contex的引用,但是,当Drawable与View连接之后,Drawable就将View设置为一个回调,由于View中是包含Context的引用的,所以,实际上我们依然保存了Context的引用。这个引用链如下:

    Drawable->TextView->Context

    所以,最终该Context也没有得到释放,发生了内存泄露。

    如何才能有效的避免这种引用的发生呢?

    第一,应该尽量避免static成员变量引用资源耗费过多的实例,比如Context。

    第二、Context尽量使用Application Context,因为Application的Context的生命周期比较长,引用它不会出现内存泄露的问题。

    第三、使用WeakReference代替强引用。比如可以使用WeakReference<Context> mContextRef;

    该部分的详细内容也可以参考Android文档中Article部分。

四、都是线程惹的祸

    线程也是造成内存泄露的一个重要的源头。线程产生内存泄露的主要原因在于线程生命周期的不可控。我们来考虑下面一段代码。

  1. public   class  MyActivity  extends  Activity {  
  2.     @Override   
  3.     public   void  onCreate(Bundle savedInstanceState) {  
  4.         super .onCreate(savedInstanceState);  
  5.         setContentView(R.layout.main);  
  6.         new  MyThread().start();  
  7.     }  
  8.   
  9.     private   class  MyThread  extends  Thread{  
  10.         @Override   
  11.         public   void  run() {  
  12.             super .run();  
  13.             //do somthing   
  14.         }  
  15.     }  
  16. }  

 

    这段代码很平常也很简单,是我们经常使用的形式。我们思考一个问题:假设MyThread的run函数是一个很费时的操作,当我们开启该线程后,将设备的横屏变为了竖屏,一般情况下当屏幕转换时会重新创建Activity,按照我们的想法,老的Activity应该会被销毁才对,然而事实上并非如此。

    由于我们的线程是Activity的内部类,所以MyThread中保存了Activity的一个引用,当MyThread的run函数没有结束时,MyThread是不会被销毁的,因此它所引用的老的Activity也不会被销毁,因此就出现了内存泄露的问题。

\"></p>
<p style=winux ” 博客,谢绝转载!

分享到:
评论

相关推荐

    Android 帧动画优化实现可减少内存使用

    本篇文章将深入探讨如何优化Android帧动画以降低内存使用。 首先,理解帧动画的工作原理至关重要。帧动画是通过`AnimationDrawable`类实现的,它是一个可绘制对象,可以包含一系列`&lt;frame&gt;`元素,每个元素代表一帧...

    Android解决大量帧动画内存泄漏问题

    帧动画太多造成内存泄漏问题,内含所需的JAR包:org.apache.commons.io.IOUtils,将Inputstream转为byte字节数组,减少内存泄漏 和关键代码,仅供参考,如有建议请在下方留言或添加咨询~~~

    面向Android系统的动态内存管理策略.pdf

    然而,由于Android系统将存储子系统全部放在Linux用户空间内,导致其无法直接获得大块连续物理内存,这就需要在Linux内存管理中增加PMEM(physical memory)管理区来解决这个问题。 PMEM管理机制的提出正是为了解决...

    android实现火箭动画清理内存

    "android实现火箭动画清理内存"这个主题就是关于如何在Android应用程序中结合火箭动画来模拟一个内存清理的过程,从而为用户提供一种直观且有趣的交互方式。在这个过程中,我们将深入探讨`Animation`类和`...

    Android智能手机动态内存取证技术综述.pdf

    Android智能手机动态内存取证技术综述 Android智能手机动态内存取证技术综述是指在Android智能手机中,通过各种技术手段对动态内存中的敏感数据进行提取、分析和恢复,以获取电子证据,用于电子取证和犯罪侦查等...

    Android-ImageFrame高效省内存播放序列帧动画控件

    `Android-ImageFrame`控件就是针对这个问题提供的一种高效、省内存的解决方案。 `Android-ImageFrame`控件主要特点在于: 1. **高效内存复用**:该控件实现了内存复用机制,这意味着它可以在播放序列帧时,只需要...

    Android 内存溢出问题

    在Android开发中,内存管理是优化应用程序性能的关键因素之一。内存溢出问题,尤其是在处理大量数据或资源时,可能导致应用程序崩溃或性能下降。本篇文章将深入探讨Android内存管理的两个核心概念:堆(Heap)和栈...

    Android 获取手机总内存和可用内存信息,博客附adb方式

    在Android系统中,获取手机的总内存和可用内存信息是开发者和普通用户都可能需要的操作。这涉及到系统层面的信息查询,通常需要通过编程接口(API)或者使用Android Debug Bridge(ADB)工具来实现。以下是对这个...

    Android-WaveLineView一款性能内存友好的录音波浪动画

    《Android-WaveLineView:打造性能与内存优化的录音波浪动画》 在Android应用开发中,动画效果是提升用户体验的重要一环。特别是在音乐、录音等应用中,波浪动画可以直观地展示声音的动态变化,使用户感受到更加...

    Android获取cpu,内存,磁盘使用率信息

    在Android平台上,获取CPU、内存和磁盘使用率信息对于开发者来说是十分重要的,这有助于监控设备性能,优化应用运行,以及提供用户友好的反馈。然而,由于Android系统的安全机制,不同的权限级别决定了你能获取到何...

    Android webview 内存泄露的解决方法

    Android webview 内存泄露的解决方法 最近在activity嵌套webview显示大量图文发现APP内存一直在涨,没法释放内存,查了很多资料,大概是webview的一个BUG,引用了activity导致内存泄漏,所以就尝试传递...

    Android转场动画-Activity_Transition

    在Android开发中,转场动画(Transition)是提升用户体验的重要组成部分,尤其是在Activity之间的切换过程中。Activity_Transition是指在Android应用程序中,当一个Activity淡出,另一个Activity淡入时,所展示的...

    Android按下录音录音动画效果 ,自定义录音、播放动画View

    使用Android Studio的性能分析工具如`Systrace`和`Hprof`来检查CPU和内存使用情况,优化代码性能。 总之,实现“Android按下录音录音动画效果,自定义录音、播放动画View”需要结合自定义视图的绘制、媒体录制与...

    android性能优化之内存泄露

    ### Android性能优化之内存泄露 #### 一、内存泄露概述 在Android开发中,内存管理是确保应用程序稳定性和性能的关键因素之一。不当的内存管理可能导致内存泄露,进而引发一系列问题,如应用程序运行缓慢、崩溃...

    基于LiME工具的Android手机动态内存提取.pdf

    本文探讨了如何利用LiME(Linux Memory Extractor)工具来从不同版本内核的Android手机中提取动态内存。动态内存取证是指从易失性内存中提取信息的过程,这种内存通常用于存储临时数据,如正在运行的进程、应用程序...

    android 录音 动画

    在Android平台上,录音功能是通过MediaRecorder类实现的,而动画效果则主要依赖于View的动画API。在“android 录音 动画”这个场景中,我们需要关注以下几个关键知识点: 1. **MediaRecorder**: 这是Android SDK...

    android Animation动画实现loading效果

    在Android开发中,动画(Animation)是提升用户体验和视觉效果的重要工具之一,特别是在创建加载(Loading)效果时。本文将深入探讨如何使用Android Animation来实现动态的Loading效果。 一、Android Animation概述 ...

    Android 动态卷轴效果

    在Android开发中,动态卷轴效果通常用于实现类似滚动新闻、滚动公告或者无限滚动列表的效果。这种效果可以增强用户界面的交互性和吸引力,使信息展示更加生动。在本案例中,我们将聚焦于如何在Android应用中创建一个...

    android 图片内存溢出(OOM)解决

    基本上解决了OOM问题 如果 方便可以直接引用BitmapManager类到 项目中使用 解决blog 地址http://www.cnblogs.com/liongname/articles/2345087.html

Global site tag (gtag.js) - Google Analytics