• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android应用程序内存泄漏介绍

Android应用程序内存泄漏介绍

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android应用程序开发,android应用程序,android退出应用程序,android应用程序框架,android应用程序设计等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android应用程序内存泄漏介绍


Android应用程序内存泄漏介绍


内存泄漏和内存溢出的区别

内存溢出(out of memory)是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory。比如在我们每个Android程序在运行时系统都会给程序分配一个一定的内存空间,当程序在运行中需要的内存超出这个限制就会报内存溢出(out of memory)。
内存泄漏(memory leak)是指程序在申请内存后,无法释放已申请的内存空间。多次内存无法被释放,程序占用的内存会一直增加,直到超过系统的内存限制报内存溢出。


java中为什么会发生内存泄漏

大家在学习Java的时候,可以在阅读相关书籍的时候,关于Java的优点中,第一条就是Java是通过GC来自动管理内存的回收的,程序员不需要通过调用函数来释放内存。因此,很多人认为Java不存在内存泄漏的问题,真实的情况并不是这样,尤其是我们在开发手机和平板相关的应用的时候,往往是由于内存泄漏的累计很快导致程序的崩溃。想要了解这个问题,我们需要先了解Java是如何管理内存。
Java的内存管理
Java的内存管理就是对象的分配和释放的问题,在Java中,程序员需要需要通过关键字new为每个对象申请内存空间(基本类型除外),所有的对象都在堆(Heap)中分配空间。另外,对象的释放是由GC决定和执行的。在Java中,内存的分配是由程序完成的,而内存的释放由GC完成的。这种收支两条线的确是简化了程序员的工作。但同时,它也加重了JVM的负担。这也是Java运行较慢的原因之一。因为,GC为了正确的释放每个对象,GC必须监控每个对象的运行状态,包括对象的申请,引用,被引用,赋值GC都需要监控。
监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。
为了更好理解GC的工作原理,我们可以将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用者指向被引对象。另外,每个线程对象可以作为一个图的起始顶点,例如大多程序从main进程开始执行,那么该图就是以main进程顶点开始的一棵根树。在这个有向图中,根顶点可达的对象都是有效对象,GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC回收。
以下,我们举一个例子说明如何用有向图表示内存管理。对于程序的每一个时刻,我们都有一个有向图表示JVM的内存分配情况。以下右图,就是左边程序运行到第6行的示意图。
此处输入图片的描述
Java使用有向图的方式进行内存管理,可以消除引用循环的问题,例如有三个对象,相互引用,只要它们和根进程不可达的,那么GC也是可以回收它们的。这种方式的优点是管理内存的精度很高,但是效率较低。另外一种常用的内存管理技术是使用计数器,例如COM模型采用计数器方式管理构件,它与有向图相比,精度行低(很难处理循环引用的问题),但执行效率很高。
Java中的内存泄漏
下面,我们就可以描述什么是内存泄漏。在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。
在C++中,内存泄漏的范围更大一些。有些对象被分配了内存空间,然后却不可达,由于C++中没有GC,这些内存将永远收不回来。在Java中,这些不可达的对象都由GC负责回收,因此程序员不需要考虑这部分的内存泄露。
通过分析,我们得知,对于C++,程序员需要自己管理边和顶点,而对于Java程序员只需要管理边就可以了(不需要管理顶点的释放)。通过这种方式,Java提高了编程的效率。

此处输入图片的描述
因此,通过以上分析,我们知道在Java中也有内存泄漏,但范围比C++要小一些。因为Java从语言上保证,任何对象都是可达的,所有的不可达对象都由GC管理。
对于程序员来说,GC基本是透明的,不可见的。虽然,我们只有几个函数可以访问GC,例如运行GC的函数System.gc(),但是根据Java语言规范定义, 该函数不保证JVM的垃圾收集器一定会执行。因为,不同的JVM实现者可能使用不同的算法管理GC。通常,GC的线程的优先级别较低。JVM调用GC的策略也有很多种,有的是内存使用到达一定程度时,GC才开始工作,也有定时执行的,有的是平缓执行GC,有的是中断式执行GC。但通常来说,我们不需要关心这些。除非在一些特定的场合,GC的执行影响应用程序的性能,例如对于基于Web的实时系统,如网络游戏等,用户不希望GC突然中断应用程序执行而进行垃圾回收,那么我们需要调整GC的参数,让GC能够通过平缓的方式释放内存,例如将垃圾回收分解为一系列的小步骤执行,Sun提供的HotSpot JVM就支持这一特性。


Android内存泄漏总结
在我们开发Android程序的时候,经常会遇到内存溢出的情况,在我们这次Launcher的开发过程中,就存在内存泄漏的问题。下面结合我们在Launcher开发中遇到的实际问题,分享一下内存泄漏怎么解决。

Android中常见内存泄漏

集合类泄漏

集合类如果仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用。如果这个集合类是全局性的变量(比如类中的静态属性,全局性的 map 等即有静态引用),那么没有相应的删除机制,很可能导致集合所占用的内存只增不减。请看下面的示例代码,稍不注意还是很容易出现这种情况,比如我们都喜欢通过HashMap做一些缓存之类的事,这种情况就要多留一些心眼。

    ArrayList list = new ArrayList();
    for (int i = 1; i < 100; i++) {
        Object o = new Object();
        v.add(o);
        o = null;   
    }

在上面的代码中list是一个全局变量,仅仅在后面把对象的引用置空是没有用的,因为对象被list持有,在本类生命周期没有结束的情况下,是不会被gc回收的。

单例造成的内存泄漏。

由于单例的静态特性使得其生命周期跟应用的生命周期一样长,所以如果使用不恰当的话,使单例持有的对象一直存在,很容易造成内存泄漏。比如下面一个典型的例子:

    public class AppManager {
        private static AppManager instance;
        private Context context;
        private AppManager(Context context) {
            this.context = context;
        }
        public static AppManager getInstance(Context context) {
        if (instance == null) {
        instance = new AppManager(context);
        }
        return instance;
        }
        }

上面的例子中如果传进来的Context是Activity,AppManager是静态的变量,它的生命周期和Application是一样的。由于该Activity一直被该该instance 一直持有,所以传进来的Activity无法被回收。将会产生内存泄漏。解决方法:此处可以传入Application,因为Application的生命周期是从开始到结束的。

非静态内部类创建静态实例造成的内存泄漏

非静态内部类默认持有该类,如果在本类中它的实例是静态的,就表示它的生命周期是和Application一样长。那么默认非静态内部类的静态实例持有了该类,该资源不会被gc掉,导致内存泄漏。

public class MainActivity extends Activity{

     private static LeakInstance mLeakInstance;
     @override
     public void onCreate(Bundle onsaveInstance){
        ......
     }

     class LeakInstance{
         .....
     }
}

上面的代码片段中,LeakInstance 是一个在Activity中的内部类,它有一个静态实例mLeakInstance,该静态实例的生命周期和Application是一样的,同时它默认持有了MainActivity,这样会导致Activity不会被gc掉,导致内存泄漏。

匿名内部类运行在异步线程。

匿名内部类默认持有它所在类的引用,如果把这个匿名内部类放到一个线程中取运行,而这个线程的生命周期和这个类的生命周期不一样的时候,会导致该类被线程所持有,不能释放。导致内存泄漏。请看如下示例代码:

public class MainActiviy extends Activity{

   private Therad mThread = null;

   private Runnable myRunnable = new Runnable{
        public void run{
           ......

        }
   }
       protected void onCreate(Bundle onSaveInstance){
               .......
              mThread = new Thread(myRunnable);
              mThread.start();
       }
}

在上面的例子中myRunnable 持有了MainActiviy,mThread的生命周期和Activity不一样,MainActiviy会被持有直到Thread运行结束。导致内存泄漏。

Handler 造成的内存泄漏

Handler 的使用造成的内存泄漏问题应该说是最为常见了

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android程序中--不能改变的事情,android程序--改变
  • Android应用程序安装过程浅析
  • Android应用程序内存泄漏介绍
  • Android应用开发必备的20条技能
  • Android程序版本更新--通知栏更新下载安装,android程序版本

相关文章

  • 2017-05-26ORB_SLAM2在Android上的移植过程
  • 2017-05-26单机搭建Android开发环境(一),单机搭建android开发
  • 2017-05-26Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define ...,dalvikdex
  • 2017-05-26【开源】二维码签到手机andriod版下载!,开源签到andriod
  • 2017-05-26android 图片加载库 Glide 的使用介绍,
  • 2017-05-26菜鸟新闻3--ViewDragHelper详解(侧滑栏),viewdraghelper侧滑
  • 2017-05-26Android热更新开源项目Tinker集成实践总结,androidtinker
  • 2017-05-26lesson15-QT多线程
  • 2017-05-26关于使用底部菜单栏的使用。。。,使用底部菜单栏..
  • 2017-05-26在Android应用程序使用YouTube API来嵌入视频,

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Android窗口机制分析与UI管理系统,androidui
    • WeakReference在Handler中的应用,weakhandler
    • android gridview画分割线
    • Android--Handler的使用方法:在子线程中更新界面
    • TabLayout和ViewPager简单实现页卡的滑动,tablayoutviewpager
    • 手动配置 Android SDK,配置androidsdk
    • APP级别处理未捕获异常,APP级别处理捕获
    • Android安全攻防战,反编译与混淆技术完全解析(上)
    • Android深入四大组件(四)广播的注册、发送和接收过程
    • Android生命周期,activity生命周期

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有