移动开发的内存管理

2017-07-30  本文已影响0人  一叶也知秋

移动系统对资源的限制和要求

移动操作系统现对于PC端的一个首要特点就是资源有限,比如内存、电池、网络的不确定等等,这些资源相对于PC端来说都很有限,当然对于发展到今天的移动端设备来说,这个已经不算是一个大问题了,不过,在移动端开发中,针对资源有限的问题都是一个不得不正视的问题。本文主要针对内存这一块进行阐述,针对移动网络的特点、电池优化的问题、有后续系列阐述文章。

移动操作系统的几个主要特点

Android内存管理机制浅析

Android是2007年Google在收购基础上推出的基于Linux操作系统的开源移动操作系统,该平台由操作系统、中间件、用户界面和应用软件组成。

Android的系统架构和其操作系统一样,采用了分层的架构。[ Android结构

Android结构

从架构图看,Android分为四个层,分别是应用程序层、应用程序框架层、系统运行库层和Linux层。

Android应用开发

在Android平台上开发应用程序,包括java 和C++(for Native)。

android平台的内存管理

一般情况下(多进程例外)每个应用都会由系统分配一个进程(zygote)资源。这段Android代码可以获取当前进程的内存情况。

        ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
        int memClass = activityManager.getMemoryClass();
        int maxClass = activityManager.getLargeMemoryClass();

任何一个进程最多可以获取的内存资源时有限的。

内存优化思路

强引用与弱引用

  • 在一个Activity生命周期中,其中所有定义的变量的生命周期都和Activty保持一致,如果用强引用的话,那么变量所指向的内存和Activity生命周期保持一致,但是在很多情况下,从逻辑上这个成员变量已经不需要了,由于强引用其所指向的内存区域也保持一样的什么周期,有点得不偿失。
  • 这种情况下,可以选择弱引用,所谓弱引用就是指其指向的内存区域,在内存比较紧张的时候可以被GC。这样就可以减少内存的使用。
    WeakReference<ForeEngine> mWeakForeEngine;
    ForeEngine  mForeEngine;

其中:

  • mForeEngine是强引用,mWeakForeEngine是弱引用
  • mWeakForeEngine指向的内存在mWeakForeEngine运行过程中可能会被回收

弱引用的初始化

     mWeakForeEngine  = new WeakReference<ForeEngine>(foreEngine) ;

弱引用的使用

      ForeEngine foreEngine = mWeakForeEngine.get();
     if(foreEngine == null) {
     //  todo
     }

关注内存大户Bitmap

待续

Android内存管理原理简析

Java虚拟机模型

JVM内存模型,java虚拟机在构建RunTime运行时数据内存分配,
内存主要分为方法区,虚拟机栈,本地方法栈,堆,PCR程序计数器。

JVM内存模型示意

Android的改进

- 寄存器和栈的区别
     * JVM虚拟机基于栈,DVM基于寄存器。*
- Dalvik和java虚拟的区别  dex class的区别
-  dalvik art的改进
   android虚拟机都使用页式和memory mapping方式进行内存管理,虚拟机分配并决定了内存的生命周期,并且使用GC(*garbage collection*)来回收已分配但是不再使用的内存片段,GC的主要工作主要分为两个部分:
     1)找到内存中不再使用的数据片段
     2)回收这些资源
   分配内存资源主要是分代管理,刚刚分配的内存区域叫Young Generation。
   对象在Young Generation时间比较长之后,就会被划到Older Generation,还有一个permanent generation。
    尽管内存回收的速度较快,但是由于会在程序运行过程中的停下执行GC,不可避免的的会影响程序的运行,一旦GC边界条件被触发,系统就会停止当前进程,开始GC。
    关于GC的详细机制详见,ref:
- Android Runtime(ART)的进一步改进措施
    1) ART中暂停次数相比于Dalvik有减少,从两次减为一次;
    2)ART GC 一样有暂停中断,不一样之处在于,ART在有些阶段比如引用过程,sytem sweeping过程,等阶段中可以并发的执行GC。

DVM算法简析

\dalvik\vm\Init.cpp
/*
* VM initialization.  Pass in any options provided on the command line.
* Do not pass in the class name or the options for the class.
*
* Returns 0 on success.
*/
std::string dvmStartup(int argc, const char* const argv[],
bool ignoreUnrecognized, JNIEnv* pEnv)

其中 启动的内容很多,有兴趣的可以参考源代码。

2 GC 启动

在main heap上采用mmap管理内存。
dalvik\vm\alloc\alloc.cpp

/*
* Initialize the GC universe.
*
* We're currently using a memory-mapped arena to keep things off of the
* main heap.  This needs to be replaced with something real.
*/
bool dvmGcStartup()
{
dvmInitMutex(&gDvm.gcHeapLock);
pthread_cond_init(&gDvm.gcHeapCond, NULL);
return dvmHeapStartup();
}

3 GC heap启动

dalvik\vm\alloc\Heap.cpp
初始化GC heap 并建立VM card table。

/*
* Initialize the GC heap.
*
* Returns true if successful, false otherwise.
*/
bool dvmHeapStartup()
{
GcHeap *gcHeap;
if (gDvm.heapGrowthLimit == 0) {
gDvm.heapGrowthLimit = gDvm.heapMaximumSize;
}
gcHeap = dvmHeapSourceStartup(gDvm.heapStartingSize,
gDvm.heapMaximumSize,
gDvm.heapGrowthLimit);
if (gcHeap == NULL) {
return false;
}
gcHeap->ddmHpifWhen = 0;
gcHeap->ddmHpsgWhen = 0;
gcHeap->ddmHpsgWhat = 0;
gcHeap->ddmNhsgWhen = 0;
gcHeap->ddmNhsgWhat = 0;
gDvm.gcHeap = gcHeap;
/* Set up the lists we'll use for cleared reference objects.
*/
gcHeap->clearedReferences = NULL;
if (!dvmCardTableStartup(gDvm.heapMaximumSize, gDvm.heapGrowthLimit)) {
LOGE_HEAP("card table startup failed.");
return false;
}
return true;
}

4

dalvik\vm\alloc\HeapSource.cpp
为了不和zygote heap的内存发生交集,在首次fork之前调用它,这个仍然会有一些造成小片段内存的问题存在

/*
* This is called while in zygote mode, right before we fork() for the
* first time.  We create a heap for all future zygote process allocations,
* in an attempt to avoid touching pages in the zygote heap.  (This would
* probably be unnecessary if we had a compacting GC -- the source of our
* troubles is small allocations filling in the gaps from larger ones.)
*/
bool dvmHeapSourceStartupBeforeFork()
{
HeapSource *hs = gHs; // use a local to avoid the implicit "volatile"
HS_BOILERPLATE();
assert(gDvm.zygote);
if (!gDvm.newZygoteHeapAllocated) {
/* Ensure heaps are trimmed to minimize footprint pre-fork.
*/
trimHeaps();
/* Create a new heap for post-fork zygote allocations.  We only
* try once, even if it fails.
*/
ALOGV("Splitting out new zygote heap");
gDvm.newZygoteHeapAllocated = true;
return addNewHeap(hs);
}
return true;
}
上一篇 下一篇

猜你喜欢

热点阅读