Android内存优化——概述

Android 应用运行在 Java 虚拟机上,每打开一个 Android app 都会打开一个独立的虚拟机。运行虚拟机时会在设备的寄存器上开辟一块内存空间作为虚拟机的内存区域。虚拟机的内存区域一般划分为堆、栈、方法区/静态存储区、运行时常量池、本地方法栈等。

堆、栈

堆是不连续的内存区域(因为系统是用链表来存储堆中的空闲内存地址)。堆上分配内存的过程为动态分配过程,在堆中存放由 new 关键字创建的对象或数组。堆的内存管理是由 Java 的 GC(垃圾回收机制)来管理的。通常我们所说的内存优化即是堆内存的优化。

栈是针对线程来说的,每个线程都有一个栈。栈中主要存放基本类型的变量对象的引用,并且对象本身是没有存放在栈中,而是存放在堆中的。

当方法执行时,方法内部的局部变量被创建,基本类型的变量会直接存放在栈中,引用类型的变量则会将该引用变量在堆中的内存地址存放在栈中。方法执行结束时,这些局部变量在栈中所占的内存空间就会被释放。

举个例子:

public class Person {
    int i = 1;
    Girl g1 = new Girl();

    public void x() {
        int j = 1;
        Girl g2 = new Girl();
        Girl g3 = g1;
    }
}

ig1为成员变量,jg2g3为方法x()中的局部变量,ig1字段属于类,类最终是要被new出来。所以ig1存放在堆中的。j为基本类型,作为局部变量肯定是存放在栈中的。g2g3都为引用类型,它们引用的对象实体是存放在堆中的,在栈中只存有他们的引用(堆中的内存地址),当方法执行结束后,栈中的引用被释放。

总结: 成员变量(基本类型和引用类型)全部存储在堆中;基本类型的局部变量存储在栈中;引用类型的局部变量的对象实体是存在堆中,栈中只存有它的引用。

垃圾回收器 GC

栈内存的特点是效率高、速度快,并且在方法结束时就自动释放,但是它的容量有限。而堆内存空间的释放完全依赖于 GC 。在程序的运行过程中,GC 会不定时的被唤醒检查是否有没有被引用的对象,并释放他们的空间。

一般在堆内存占用较多(内存不足)的空闲时候系统可能会自动执行垃圾回收。但是垃圾回收机制只针对“垃圾”有效。所谓垃圾,是指存在于堆中,并且程序不能再访问到的对象(不可达的对象)。GC 在执行垃圾回收时,会将不可达的对象放入垃圾回收器中,而对于那些还处于引用状态即可达对象 GC 会根据该对象的引用状态来决定是否回收。

Java中对象的引用状态有强引用、软引用、弱引用、虚引用4种。

强引用

强引用是使用最普遍的引用方式,我们平常使用的大部分引用都是强引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠回收具有强引用的对象来解决内存不足的问题。

软引用

一个对象具有软引用,如果内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        SoftReference<Person> sr = new SoftReference<Person>(person);
        person = null;
        if (sr != null) {
            person = sr.get();
        } else {
            person = new Person();
            sr = new SoftReference<Person>(person);
        }
    }
}
弱引用

在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        WeakReference<Person> wr = new WeakReference<Person>(person);
        person = null;
        if (wr != null) {
            person = wr.get();
        } else {
            person = new Person();
            wr = new WeakReference<Person>(person);
        }
    }
}
虚引用

如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收的活动,我们平常一般不会使用。

需要注意的是,GC 什么时候回收垃圾是无法控制的,垃圾回收时间也是无法预料的。

GC 内存管理机制虽然能帮助我们自动管理内存,避免了程序员主动释放内存的繁琐工作,但它不能解决所有的问题。GC不能回收的对象可能会导致内存泄露,甚至使整个程序发生OOM。

内存泄露

当一个对象在程序执行过后已经不需要再使用了,但是有其他的对象仍然持有该对象的引用,以致该对象不能被 GC 回收,那么这个对象会一直占据内存,从而导致该内存不可用。这种本该被GC回收(不再需要用了)而又不能被回收(被其他对象持有引用)以致停留在堆内存中的对象就造成了内存泄露。

内存溢出

内存溢出,OutOfMemory ,即 我们通常所说的OOM,是指程序在申请内存时,没有足够的内存空间供其使用。

在Android中,有以下几种情况可能发生内存溢出:
1.内存泄露可能导致内存溢出的发生;
2.一次加载的数据量过大,如一次从数据库读取过多数据;
3.保存了许多耗用内存过大的对象(如Bitmap)或加载单个超大的图片,造成内存超出限制;
4.代码中存在死循环或循环产生过多重复的对象实体。

GC能自动回收并释放无用的对象,但是如果程序频繁的GC也会导致一些问题。

频繁GC

程序在执行GC操作的时候,任何线程的任何操作都会需要暂停,等待GC操作完成之后,其他操作才能够继续运行。故而如果Andorid应用频繁GC,UI线程有可能会暂停,从而导致导致界面卡顿。

导致频繁GC主要有两个方面的原因:
1.内存抖动, 即大量的对象被创建又在短时间内马上被释放。
2.瞬间产生大量对象会严重占用内存区域,当达到阀值, 剩余空间不够的时候,就会触发GC。即使每次分配的对象需要占用很少的内存,但是他们叠加在一起会增加堆内存的压力, 从而触发更多的GC。


OK,Android内存优化的概述就到此为止。后面会详细介绍Android中的内存泄露及相关优化。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容