Android内核读书笔记(3)—Android内存管理

一、应用程序关闭而不退出
        1.关闭-->仅仅是窗口不可见,但其对应的进程还存在
        如果后台有许多进程存在的话,只会占用内存空间,而不会降低前台进程的运行速度,为什么?
        
        每个应用程序主体--->ActivityThread,该类初始化后会进入消息循环(Looper.loop)当中
        
        以后则靠消息机制,有消息就处理消息,没有消息就sleep
        
        在queue.next方法中会从消息内部取出消息,如果没有消息则会sleep当前的线程,直到有新消息到来时会唤醒next()方法

        queue.next()方法被唤醒的三种情况:
            a.定时器中断
                操作系统向定时器发送一个任务,该任务会向looper发送一个消息

            b.用户按键消息
                wms把用户按键消息发送到looper主线程

            c.Binder中断
                Binder-->Linux的一个驱动
                应用程序中可以包含一个binder对象---->     Binder驱动接收binder消息派发给客户端binder对象--->binder消息处理中会向looper主线程发送一个消息

        2.Android与Linux的配合
               Android官方文档指出Activity占用的内存只有在内存不够用的时候才会被回收,而内存是否够用属于Linux内核管理,Ams并不知道
        
                Ams运行在java环境,当java环境内存低时会抛出oom异常,但这并不代表应用程序内存就很低,因为
                    i.应用程序与Ams运行在两个独立的java虚拟机中,应用程序申请内存并不会通知Ams
                    ii.java虚拟机运行时都有自己独立的内存空间
                综上,单纯的Ams是无法知道系统内存是否低的

                什么是系统内存低?
                    Android中并未采用虚拟内存,故应用程序使用的内存大小取决于物理内存的大小,系统内存低就意味着物理内存所剩无几
        
                Android中运行了一个OOM 进程--->系统启动时会向linux内核注册为一个OOM Killer--->当内存低时linux内核的内存管理模块会通知oom killer---->
                oom killer会根据各种规则进行内存释放

                Android中的oom killer进程仅适用于Android应用程序,Ams会把每一个应用程序的oom_adj值告诉给oom killer,该值类似于linux的nice值,在-16到15之间,
                值越小说明越重要  

        3.各种关闭程序的过程
        
                    i.startActivity开始
                        startActivity--->暂停当前Activity--->Ams收到Binder消息--->Ams.completePaused--->将activity添加进mStoppingActivities列表  
                        --->目标Activity启动,向Ams发送请求内存回收的消息--->Ams.activityIdleInternal--->调用stopActivityLocked,处理mStoppingActivities中的
                        activity--->ActivityThread.stop---->Ams.activityStopped--->trimApplications
                    
                    ii.按back键
                        finishActivityLocked--->startPausingLocked--->Ams.completePaused--->finish状态为true--->finishingActivityLocked

                    iii.向Ams发送Idle消息
                        activityIdleInternal--->trimApplication

                    iv.释放内存的3个地点
                        a.在Ams中进行
                        b.在OOMKiller中进行,Ams告诉oomkiller各个应用进程的优先级,然后oomkiller会调用linux的内核中的内存管理根据优先级杀掉进程
                        c.应用进程本身之中,通知ActivityThread.scheduleLowMemory和ActivityThread.processInBackground
        

        4.释放内存详解
            a.activityIdleInternal被调用的各种原因
                
                i.handleResumeActivity--->addIdleHandler(new Idler())--->Idler.queueIdle--->Ams.activityIdle
                ii.HistoryRecord.windowVisible--->发送IDLE_NOW_MSG--->Ams.activityIdle
                iii.Ams.completePausedLocked
                    
                iv.completeResumeLocked中发生超时--->发送IDLE_TIMEOUT_MSG--->activityInternal
                v. activityInternal方法的内部实现
                    1).通知所有需要回收的客户线程(mProcessesToGc中的进程)进行内存回收
                    2).取出 mStoppingActivities 列表中的内容,并存放到临时列表stops 中,再取出mFinishigActivities
列表中的内容,并存放到临时列表finishes 中,然后删除原有的记录
                        
                    3).对stops的activity列表进行处理,改处理过程中为什么要判断finish是否为true?
                        因为按下“Back”键后,finishing 状态true,接着在completePaused()
                        中调用到了finishCurrentActivity ( 3 个参数)函数, 该函数中则会把指定的Activity 添加到
                        mStoppingActivities 列表中,显然,此时该Activity 的finishing 状态为true
                        
                        stopActivtyLocked通知目标进程ActivityThread调用onStop
                    4).接着对finish列表中的对象进行处理
                        
                    ps:以上2、3、4步并没有对客户进程进行主动的内存回收,仅仅是针对不同状态通知
                         客户进程执行不同的回调而已
                    5).调用trimApplications,真正意义上的对内存进行回收
        
                vi. trimApplications方法内部执行原理
                    1).删除mRemovedProcesses中的进程
                                mRemovedProcesses进程的来源?
                                   1.1 当某个进程crash
                                   1.2 当某个程序的UI 线程在5 秒之内没有响应时,系统会弹出一个ANR 对话框,此时如
                                         果用户选择强制关闭,该进程就会被添加到该列表
                                   1.3 当 程 序 员 调 用 AmS 提供的killBackgroundProcess() 方法时 
                                   1.4 当系统启动时,AmS 的systemReady()方法中,如果发现启动了非persistent 类型的应
                                         用进程,则把这些进程添加到列表
                     2).调用updateOomAdjLocked方法,告诉OOM Killer 指定进程的优先级,若底层的linux系统包含OOMkiller,
                         则返回true,否则返回false
                     3).若上一步返回false,则优先杀死后台activity
                     4).经过以上三步后,若此时的activity数量依然超过阀值,则继续销毁满足一下三个条件的activity:
                            4.1 activity已经stop了,但是没有finish
                            4.2 不可见的activity
                            4.3 不是persistent类型的

                vii.updateOomAdjLocked(ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP)  告诉OOM 进程指定应用进程的优先级
                      a).computeOomAdjLocked计算当前进程的adj值
                    1.估算指定线程的oom_adj值
                        
                        1.1 如果该进程是TOP_APP
                                
                        1.2 如果进程中包含instrumentationClass
                                
                        1.3 如果包含正在执行的receiver对象
                                
                        1.4 包含正在执行的service对象
                                
                        以上几步都是最高优先级
            
                        1.5 如果包含前台服务对象
                                
                    
                        1.6 如果进程正在被用户强制调到前台
                                
                        1.7 如果为home进程
                                
                        1.8 如果当前activity的数目大于0并且visible
                                
                        1.9 如果是空进程
                                
                        综上,以上几步得到的adj值是一个rawAdj,也就是源码中的unlimited,即无限制条件下应有的优先级值
                                

                    2.对于service和provider的adj值
                        2.1 如果是备份进程
                                
                        2.2 处理当前进程中非前台service(即该service不属于前台进程,也没有和前台进程交互)
                            2.2.1 该app所包含的service的优先级大于前台进程并且所在调度组为背景非交互                                    
 
                            2.2.2 该service被请求启动过,并且没超过打击时间(30分钟),优先级设为SECONDARY_SERVER_ADJ
                                        
                            2.2.3 处理和该service连接的客户端,并根据其客户端的优先级调整其service的优先级,如果客户端是该进程本身,不作处理
 
                                    
                            2.2.4 如果是BIND_AUTO_CREATE方式创建的service
                                     
                        2.2.5 判断客户连接对应的activity
                                
 
                    2.3. 处理provider的情况(与service基本相同)
                        
 
                    2.4 查看上述的adj值是否超过系统给定的对大值
                            
 
                    
                b) 1.判断当前app是否需要从前台切换到后台
                        
 
                    2. 真正的adj值已改变
                        
 
                    3. 所在调度组发生变化
                    
                      
            viii.判断当前app的curAdj值
                
               
            viv.Ams内部内存回收潜规则(oom killer)

            vv.scheduleAppGcLocked通知指定的app对象进行内存回收
                
                   
                    
                    performAppGcsIfAppropriateLocked :处理GC_BACKGROUND_PROCESSES_MSG消息
                    
                        canGcNowLocked:判断是否适合进行回收
                        
                        即:
                            .当前没有正在执行的Broadcastreceiver
                            .当前处于sleep状态或者正在执行的activity处于idle状态

                        performAppGcsLocked
                        
                        performAppGcLocked
                        
 
                     ps:当客户进程启动失败是会将app.reportLowMemory设置为true
                    
                    ActivityThread.scheduleLowMemory
                        
 
                    ActivityThread.handleLowMemory处理上面的方法
                         
                    
                    processInBackground方法
                                
                            
                ps: processInBackground方法只会回收Binder相关的内存

        5.如何理解activity
            a. Activity并不对应一个应用程序,ActivityThread才对应一个应用程序
            b. 默认activity会添加一个窗口,但实际上可以修改,使其不添加任何窗口
            c. 在系统内存低的时候会释放调显存
                        
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. Android 的基本概念 Android 是一个开源的操作系统,主要用于移动设备,如智能手机、平板电脑等。它基于 Linux 内核,提供了丰富的应用程序框架和 API,支持多种开发语言,如 Java、C/C++、Kotlin 等。 Android 应用程序由多个组件组成,包括活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供器(Content Provider)等。这些组件可以组合在一起,形成复杂的应用程序。 2. Android 应用程序开发 Android 应用程序开发主要使用 Java 编程语言和 Android SDK。开发工具包括 Android Studio、Eclipse 等。 Android 应用程序的结构包括布局文件、资源文件、Java 代码和清单文件等。布局文件用于定义应用程序的用户界面,资源文件包括图像、声音、样式、主题等,Java 代码实现应用程序的逻辑,清单文件描述应用程序的组件和权限等信息。 3. Android 应用程序的调试和测试 Android 应用程序的调试和测试可以使用 Android Studio 提供的调试工具,包括断点调试、日志记录等。还可以使用模拟器或真实设备进行测试。 4. Android 应用程序的发布 发布 Android 应用程序需要进行签名和打包操作,签名用于验证应用程序的身份和完整性,打包将应用程序打包成 APK 文件,可以上传到应用商店进行发布。 5. Android 应用程序的优化 Android 应用程序的优化包括优化布局、资源、代码和网络等方面,以提高应用程序的性能和用户体验。其中,布局优化包括使用布局最优化算法、使用自定义视图等;资源优化包括压缩资源、使用向量图形等;代码优化包括使用异步任务、使用缓存等;网络优化包括使用数据压缩、使用本地存储等。 6. Android 开发的挑战 Android 开发面临的挑战包括设备碎片化、安全问题、性能问题等。设备碎片化指的是不同设备的屏幕尺寸、分辨率、操作系统版本等不同,需要对应用程序进行适配;安全问题指的是应用程序需要保证用户数据的安全和隐私;性能问题指的是应用程序需要保证快速响应和流畅运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值