添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

通过前面一系列文章的学习,我们知道了ART运行时既支持Mark-Sweep GC,又支持Compacting GC。其中,Mark-Sweep GC执行效率更高,但是存在内存碎片问题;而Compacting GC执行效率较低,但是不存在内存碎片问题。ART运行时通过引入Foreground GC和Background GC的概念来对这两种GC进行扬长避短。本文就详细分析它们的执行过程以及切换过程。

老罗的新浪微博: http://weibo.com/shengyangluo ,欢迎关注!

《Android系统源代码情景分析》一书正在进击的程序员网( http://0xcc0xcd.com )中连载,点击进入!

在前面 ART运行时Compacting GC简要介绍和学习计划 ART运行时Compacting GC堆创建过程分析 这两篇文章中,我们都有提到了ART运行时的Foreground GC和Background GC。它们是在ART运行时启动通过-Xgc和-XX:BackgroundGC指定的。但是在某同一段时间,ART运行时只会执行Foreground GC或者Background GC。也就是说,Foreground GC和Background GC在整个应用程序的生命周期中是交替执行的。这就涉及到从Foreground GC切换到Background GC,或者从Background GC切换到Foreground GC的问题。

现在两个问题就来了:什么时候执行Foreground GC,什么时候执行Background GC?什么GC作为Foreground GC最合适,什么GC作为Background GC最合适?

顾名思义,Foreground指的就是应用程序在前台运行时,而Background就是应用程序在后台运行时。因此,Foreground GC就是应用程序在前台运行时执行的GC,而Background就是应用程序在后台运行时执行的GC。

应用程序在前台运行时,响应性是最重要的,因此也要求执行的GC是高效的。相反,应用程序在后台运行时,响应性不是最重要的,这时候就适合用来解决堆的内存碎片问题。因此,Mark-Sweep GC适合作为Foreground GC,而Compacting GC适合作为Background GC。

但是,ART运行时又是怎么知道应用程序目前是运行在前台还是后台呢?这就需要负责管理应用程序组件的系统服务ActivityManagerService闪亮登场了。因为ActivityManagerService清楚地知道应用程序的每一个组件的运行状态,也就是它们当前是在前台运行还是后台运行,从而得到应用程序是前台运行还是后台运行的结论。

我们通过图1来描述应用程序的运行状态与Foreground GC和Background GC的时序关系,如下所示:

图1 应用程序运行状态与Foreground GC和Background GC的时序关系

从图1还可以看到,当从Foreground GC切换到Background GC,或者从Background GC切换到Foreground GC,会发生一次Compacting GC的行为。这是由于Foreground GC和Background GC的底层堆空间结构是一样的,因此发生Foreground GC和Background GC切换时,需要将当前存活的对象从一个Space转移到另外一个Space上去。这个刚好就是Semi-Space GC和Generational Semi-Space GC合适干的事情。

图1中的显示了应用程序的两个状态:kProcessStateJankPerceptible和kProcessStateJankImperceptible。其中,kProcessStateJankPerceptible说的就是应用程序处于用户可感知的状态,这就相当于是前台状态;而kProcessStateJankImperceptible说的就是应用程序处于用户不可感知的状态,这就相当于是后台状态。

接下来,我们就结合ActivityManagerService来分析Foreground GC和Background GC的切换过程。

从前面 Android应用程序的Activity启动过程简要介绍和学习计划 这个系列的文章可以知道,应用程序组件是通过ActivityManagerService进行启动的。例如,当我们从Launcher启动一个应用程序时,实际的是在这个应用程序中Action和Category分别被配置为MAIN和LAUNCHER的Activity。这个Activity最终由ActivityManagerService通知其所在的进程进行启动工作的,也就是通过ApplicationThread类的成员函数scheduleLaunchActivity开始执行启动工作的。其它类型的组件的启动过程也是类似的,这里我们仅以Activity的启动过程作为示例,来说明ART运行时如何知道要进行Foreground GC和Background GC切换的。

ApplicationThread类的成员函数scheduleLaunchActivity的实现如下所示:

public final class ActivityThread {
    ......
    private class ApplicationThread extends ApplicationThreadNative {
        ......
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
                IVoiceInteractor voiceInteractor, int procState, Bundle state,
                PersistableBundle persistentState, List<ResultInfo> pendingResults,
                List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
                ProfilerInfo profilerInfo) {
            updateProcessState(procState, false);
            ActivityClientRecord r = new ActivityClientRecord();
            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;
            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;
            r.startsNotResumed = notResumed;
            r.isForward = isForward;
            r.profilerInfo = profilerInfo;
            updatePendingConfiguration(curConfig);
            sendMessage(H.LAUNCH_ACTIVITY, r);
        ......
    ......

       这个函数定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。

       ApplicationThread类的成员函数scheduleLaunchActivity首先是调用另外一个成员函数updateProcessState更新进程的当前状态,接着再将其余参数封装在一个ActivityClientRecord对象中,并且将这个ActivityClientRecord对象通过一个H.LAUNCH_ACTIVITY消息传递给应用程序主线程处理。应用程序主线程处理对这个消息的处理就是启动指定的Activity,这个过程可以参考前面Android应用程序的Activity启动过程简要介绍和学习计划这个系列的文章。ApplicationThread类的成员函数scheduleLaunchActivity还调用了另外一个成员函数updatePendingConfiguration将参数curConfig描述的系统当前配置信息保存下来待后面处理。

       我们主要关注ApplicationThread类的成员函数updateProcessState,因为它涉及到进程状态的更新,它的实现如下所示:

public final class ActivityThread {
    ......
    private class ApplicationThread extends ApplicationThreadNative {
        ......
        public void updateProcessState(int processState, boolean fromIpc) {
            synchronized (this) {
                if (mLastProcessState != processState) {
                    mLastProcessState = processState;
                    // Update Dalvik state based on ActivityManager.PROCESS_STATE_* constants.
                    final int DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE = 0;
                    final int DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;
                    通过前面一系列文章的学习,我们知道了ART运行时既支持Mark-Sweep GC,又支持Compacting GC。其中,Mark-Sweep GC执行效率更高,但是存在内存碎片问题;而Compacting GC执行效率较低,但是不存在内存碎片问题。ART运行时通过引入Foreground GC和Background GC的概念来对这两种GC进行扬长避短。本文就详细分析它们的执行过程以及切换过程。
				
借助profiler工具进行内存分析官方链接工具说明模拟内存问题场景利用Profiler工具进行内存分析问题解决与总结 使用 Memory Profiler 查看 Java 堆和内存分配 android studio 版本3.6.1 模拟内存问题场景 建立一个新的工程,把下面有问题的自定义VIew,引入到工程里面,最好是写两个activity,把下面自定义view引入到第二个SecondActivity里面,方便测试。 public class IOSStyleLoadingView3 extends View { private final Context c
2021年论文 2021年-BSUV-Net 2.0:时空数据增强,用于视频不可知的有监督背景扣除( IEEE Access ) 2021年-用于运动目标分割的多帧循环对抗网络( CVPR-2021 ) 2021年-用于场景独立运动对象分割的深度对抗网络( IEEE信号处理字母) 2021年-用于交通和监视应用的端到端循环生成对抗网络(关于车辆技术的IEEE交易) 2020年论文 2020年- 作为浅谈JVM的垃圾收集(一)的后续文章,建议先看前文再来读这篇文章。 上一篇文章介绍了三大垃圾收集算法,而垃圾收集器就是垃圾收集算法的具体实现。本文主要介绍垃圾收集器,重点介绍CMS、G1、ZGC和Shenandoah收集器实现的细节。 年轻代收集器 Serial、ParNew、Parallel Scavenge 老年代收集器 Serial Old、Parallel Old、CMS收集器 特殊收集器 G1收集器,跨代收集
关于foregroundbackground的区别先看字面翻译,background是背景色foreground 也就是前景色,也就是说foregroundbackground相对应,顾名思义,foreground指定的drawable是在view视图的上方绘制的。先写一个简单的布局<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns
(1)Mark-Sweep Collection 标记清除算法 (2)Copying Collection 复制算法 (3)Mark-Compact Collection 标记-压缩算法 (3)Reference Counting 引用计数算法--未被art采用 目前art默认使用的GC方案: concurrent...
F2FS的GC策略 F2FS 主要以两种方式执行GC操作,即 foreground gcbackground gc。当空闲section不足时,F2FS会触发 foreground gc,而内核会周期性唤醒 background gc 进程,在系统空闲时回收空间。 文献【1】指出,F2FS 的 background gc 也不是随时随地都能触发成功的,background gc 被唤醒后会检查系统的状态是否符合条件,并仅在以下三种情况会成功触发 background gc: 设备连着充电线,用户没有
Garbage Collection and Performancehttps://msdn.microsoft.com/en-us/library/ee851764(v=vs.110).aspx https://channel9.msdn.com/posts/Maoni-Stephens-CLR-45-Server-Background-GC  https://channel9.msdn.c...
-----------------------------------------------前言君-------------------------------------------------- 正好碰到了这个foreground属性平时没怎么用到过。这次用到,就特意的去看
Because Android is designed for mobile devices, you should always be careful about how much random-access memory (RAM) your app uses. Although Dalvik and ART perform routine garbage collection (GC),
foregroundbackground是两个英文单词,分别表示前景和背景。在计算机领域中,这两个词通常用来描述应用程序的运行状态。 foreground指的是当前正在运行的应用程序,它占据了屏幕的主要部分,用户可以直接与之交互。而background则是指在后台运行的应用程序,它不会占据屏幕的主要部分,用户无法直接与之交互。 在操作系统中,foregroundbackground还有其他的含义。比如,foreground可以指当前正在运行的进程或线程,而background则可以指已经被挂起或暂停的进程或线程。这些概念在操作系统的管理和调度中非常重要。