通过前面一系列文章的学习,我们知道了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收集器,跨代收集
关于foreground与background的区别先看字面翻译,background是背景色foreground 也就是前景色,也就是说foreground与background相对应,顾名思义,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 gc 和 background 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),
foreground和background是两个英文单词,分别表示前景和背景。在计算机领域中,这两个词通常用来描述应用程序的运行状态。
foreground指的是当前正在运行的应用程序,它占据了屏幕的主要部分,用户可以直接与之交互。而background则是指在后台运行的应用程序,它不会占据屏幕的主要部分,用户无法直接与之交互。
在操作系统中,foreground和background还有其他的含义。比如,foreground可以指当前正在运行的进程或线程,而background则可以指已经被挂起或暂停的进程或线程。这些概念在操作系统的管理和调度中非常重要。