Android DVM 記憶體管理研究分析

Andorid为applayer 所设计的 DalvikVirtual Matchine 真的是包山包海, DVM的功能有, 对象生命周期管理, 行程管理, 内存管理, 安全和例外处理以及跟内存有关的资源回收机制. 里面每一项功能都算是一门大学问, 在这里就针对DVM的内存管理和资源回收机制做分析.分析的重点方向会分为Initial跟Allocate来分析.

Initial

当DVM作初始化时, 会去呼叫JNI_CreateJavaVM函数来初始化一些VM需要的环境.就从CreateJavaVM函数开始分析.

  1. //Jni.cpp  
  2. /* 
  3.  * Create a new VM instance. 
  4.  * 
  5.  * The current thread becomes the main VM thread.  We return immediately, 
  6.  * which effectively means the caller is executing in a native method. 
  7.  */  
  8. jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {  
  9.     // do something  
  10.     // 设定 JNIEnv 和 VM的数据结构  
  11.    
  12.     // 获取一个新的 JNIEnv 的物件  
  13.     JNIEnvExt* pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL);  
  14.    
  15.     //初始化 VM  
  16.      gDvm.initializing = true;  
  17.     std::string status =  
  18.             dvmStartup(argc, argv.get(), args->ignoreUnrecognized,  
  19.                       (JNIEnv*)pEnv);  
  20.     gDvm.initializing = false;  
  21.     // do something  
  22. }  
  23.    
  24. // Init.cpp  
  25. /* 
  26.  * VM initialization.  Pass in any options provided on the command line. 
  27.  * Do not pass in the class name or the options for the class. 
  28.  * 
  29.  * Returns 0 on success. 
  30.  */  
  31. std::string dvmStartup(int argc, const charconst argv[],  
  32.         bool ignoreUnrecognized, JNIEnv* pEnv)  
  33. {  
  34.      // VM init args  
  35.    
  36.      /* mterp setup */  
  37.      // 设定VM值译器  
  38.      dvmQuasiAtomicsStartup  
  39.      dvmAllocTrackerStartup  
  40.       
  41.      if (!dvmGcStartup()) {  
  42.         return "dvmGcStartup failed";  
  43.       }      
  44.      // 一些跟 DVM 相关的功能依序启动  
  45.      //dvmThreadStartup, dvmInlineNativeStartup, dvmRegisterMapStartup, ....  
  46. }  
  47.    
  48. // Alloc.cpp  
  49. /* 
  50.  * Initialize the GC universe. 
  51.  * 
  52.  * We're currently using a memory-mapped arena to keep things off of the 
  53.  * main heap.  This needs to be replaced with something real. 
  54.  */  
  55. bool dvmGcStartup()  
  56. {  
  57.     dvmInitMutex(&gDvm.gcHeapLock);  
  58.     pthread_cond_init(&gDvm.gcHeapCond, NULL);  
  59.     return dvmHeapStartup();  
  60. }  
  61.    
  62. // Heap.cpp  
  63. /* 
  64.  * Initialize the GC heap. 
  65.  * 
  66.  * Returns true if successful, false otherwise. 
  67.  */  
  68. bool dvmHeapStartup()  
  69. {  
  70.     GcHeap *gcHeap;  
  71.    
  72.     if (gDvm.heapGrowthLimit == 0) {  
  73.         gDvm.heapGrowthLimit = gDvm.heapMaximumSize;  
  74.     }  
  75.    
  76.     gcHeap = dvmHeapSourceStartup(gDvm.heapStartingSize,  
  77.                                   gDvm.heapMaximumSize,  
  78.                                   gDvm.heapGrowthLimit);  
  79.     if (gcHeap == NULL) {  
  80.         return false;  
  81.     }  
  82.     gcHeap->ddmHpifWhen = 0;  
  83.     gcHeap->ddmHpsgWhen = 0;  
  84.     gcHeap->ddmHpsgWhat = 0;  
  85.     gcHeap->ddmNhsgWhen = 0;  
  86.     gcHeap->ddmNhsgWhat = 0;  
  87.     gDvm.gcHeap = gcHeap;  
  88.    
  89.     /* Set up the lists we'll use for cleared reference objects. 
  90.      */  
  91.     gcHeap->clearedReferences = NULL;  
  92.    
  93.     if (!dvmCardTableStartup(gDvm.heapMaximumSize, gDvm.heapGrowthLimit))       
  94.     {  
  95.         LOGE_HEAP("card table startup failed.");  
  96.         return false;  
  97.     }  
  98.    
  99.     return true;  
  100. }  
  101.    
  102.    
  103. // HeapSource.cpp  
  104. /* 
  105.  * Initializes the heap source; must be called before any other 
  106.  * dvmHeapSource*() functions.  Returns a GcHeap structure 
  107.  * allocated from the heap source. 
  108.  */  
  109. GcHeap* dvmHeapSourceStartup(size_t startSize, size_t maximumSize,  
  110.                              size_t growthLimit)  
  111. {  
  112.     //do something  
  113.     /* Create an unlocked dlmalloc mspace to use as 
  114.      * a heap source. 
  115.      */  
  116.     // 划分一块内存来当heap使用  
  117.     msp = createMspace(base, kInitialMorecoreStart, startSize);  
  118.    
  119.     //初始化HeapSource. (HeapSource *hs)  
  120.    
  121.     // 初始化 Heap memory 在 mspace 的区域中  
  122.     addInitialHeap(hs, msp, growthLimit)  
  123.    
  124.     // Initialize Bitmap memory by heap memory  
  125.     dvmHeapBitmapInit(&hs->liveBits, base, length, "dalvik-bitmap-1")     
  126.     dvmHeapBitmapInit(&hs->liveBits, base, length, "dalvik-bitmap-2")     
  127.    
  128.     // 为最坏的情况配置一块足够大的stack memory 作为可以存放对象用的.  
  129.     allocMarkStack(&gcHeap->markContext.stack, hs->maximumSize)  
  130.    
  131. }  
  132.    
  133. static bool allocMarkStack(GcMarkStack *stack, size_t maximumSize)  
  134. {  
  135.     const char *name = "dalvik-mark-stack";  
  136.     void *addr;  
  137.    
  138.     assert(stack != NULL);  
  139.     stack->length = maximumSize * sizeof(Object*) /  
  140.         (sizeof(Object) + HEAP_SOURCE_CHUNK_OVERHEAD);  
  141.     addr = dvmAllocRegion(stack->length, PROT_READ | PROT_WRITE, name);  
  142.     if (addr == NULL) {  
  143.         return false;  
  144.     }  
  145.     stack->base = (const Object **)addr;  
  146.     stack->limit = (const Object **)((char *)addr + stack->length);  
  147.     stack->top = NULL;  
  148.     madvise(stack->base, stack->length, MADV_DONTNEED);  
  149.     return true;  
  150. }  
由上面一路追下来, 可以得到以下初始化的结论.

1. 先划分一块mSpace的内存来做为Heapmemory使用. 以目前的程序代码来看

这块内存的大小为 16 MB.

2. 初始化 HeapSource 结构作为配置用. 以下是 HeapSource 的结构.

  1. struct HeapSource {  
  2.         /* Target ideal heap utilization ratio; range 1..HEAP_UTILIZATION_MAX 
  3.          */  
  4.         size_t targetUtilization;  
  5.      
  6.         /* The starting heap size. 
  7.          */  
  8.         size_t startSize;  
  9.      
  10.         /* The largest that the heap source as a whole is allowed to grow. 
  11.          */  
  12.         size_t maximumSize;  
  13.      
  14.         /* 
  15.          * The largest size we permit the heap to grow.  This value allows 
  16.          * the user to limit the heap growth below the maximum size.  This 
  17.          * is a work around until we can dynamically set the maximum size. 
  18.          * This value can range between the starting size and the maximum 
  19.          * size but should never be set below the current footprint of the 
  20.          * heap. 
  21.          */  
  22.         size_t growthLimit;  
  23.      
  24.         /* The desired max size of the heap source as a whole. 
  25.          */  
  26.         size_t idealSize;  
  27.      
  28.         /* The maximum number of bytes allowed to be allocated from the 
  29.          * active heap before a GC is forced.  This is used to "shrink" the 
  30.          * heap in lieu of actual compaction. 
  31.          */  
  32.         size_t softLimit;  
  33.      
  34.         /* Minimum number of free bytes. Used with the target utilization when 
  35.          * setting the softLimit. Never allows less bytes than this to be free 
  36.          * when the heap size is below the maximum size or growth limit. 
  37.          */  
  38.         size_t minFree;  
  39.      
  40.         /* Maximum number of free bytes. Used with the target utilization when 
  41.          * setting the softLimit. Never allows more bytes than this to be free 
  42.          * when the heap size is below the maximum size or growth limit. 
  43.          */  
  44.         size_t maxFree;  
  45.      
  46.         /* The heaps; heaps[0] is always the active heap, 
  47.          * which new objects should be allocated from. 
  48.          */  
  49.         Heap heaps[HEAP_SOURCE_MAX_HEAP_COUNT];  
  50.      
  51.         /* The current number of heaps. 
  52.          */  
  53.         size_t numHeaps;  
  54.      
  55.         /* True if zygote mode was active when the HeapSource was created. 
  56.          */  
  57.         bool sawZygote;  
  58.      
  59.         /* 
  60.          * The base address of the virtual memory reservation. 
  61.          */  
  62.         char *heapBase;  
  63.      
  64.         /* 
  65.          * The length in bytes of the virtual memory reservation. 
  66.          */  
  67.         size_t heapLength;  
  68.      
  69.         /* 
  70.          * The live object bitmap. 
  71.          */  
  72.         HeapBitmap liveBits;  
  73.      
  74.         /* 
  75.          * The mark bitmap. 
  76.          */  
  77.         HeapBitmap markBits;  
  78.      
  79.         /* 
  80.          * State for the GC daemon. 
  81.          */  
  82.         bool hasGcThread;  
  83.         pthread_t gcThread;  
  84.         bool gcThreadShutdown;  
  85.         pthread_mutex_t gcThreadMutex;  
  86.         pthread_cond_t gcThreadCond;  
  87.         bool gcThreadTrimNeeded;  
  88.     };  

3. 设定好HeapSource结构中的一些属性, 就在mSpace这块内存中开始配置所要的Heapmemory.

4. 利用这块配置到的Heapmemory初始化两块名为dalvik-bitmap-1 和dalvik-bitmap-2的heapmemory.

5. 为这块配置到的Heapmemory 在配置一块足够大的mark stack memory来存放对象.

简单的说, 每一个程序中的DVM一旦启动之后就会为这个程序配置一块Heapmemory给使用. 而控制这块Heapmemory的结构就是 HeapSource.

Allocation

AndroidDVM 在配置内存时, 这时GC会检查目前的内存状态, 若内存的空间不足时, 就会开始启动回收机制. 何时会需要去配置内存, 当然就是程序中若有需要去产生一个新的对象使用时, 就会需要配置内存, 经过一番的研究, 配置内存源头是来自于 dvmAllocObject这个函数.

  1. // Alloc.cpp  
  2. /* 
  3.  * Create an instance of the specified class. 
  4.  * 
  5.  * Returns NULL and throws an exception on failure. 
  6.  */  
  7. Object* dvmAllocObject(ClassObject* clazz, int flags)  
  8. {  
  9.     Object* newObj;  
  10.    
  11.     assert(clazz != NULL);  
  12.     assert(dvmIsClassInitialized(clazz) || dvmIsClassInitializing(clazz));  
  13.    
  14.     /* allocate on GC heap; memory is zeroed out */  
  15.     newObj = (Object*)dvmMalloc(clazz->objectSize, flags);  
  16.     if (newObj != NULL) {  
  17.         DVM_OBJECT_INIT(newObj, clazz);  
  18.         dvmTrackAllocation(clazz, clazz->objectSize);   /* notify DDMS */  
  19.     }  
  20.    
  21.     return newObj;  
  22. }  
  23.    
  24. // Heap.cpp  
  25. /* 
  26.  * Allocate storage on the GC heap.  We guarantee 8-byte alignment. 
  27.  * 
  28.  * The new storage is zeroed out. 
  29.  * 
  30.  * Note that, in rare cases, this could get called while a GC is in 
  31.  * progress.  If a non-VM thread tries to attach itself through JNI, 
  32.  * it will need to allocate some objects.  If this becomes annoying to 
  33.  * deal with, we can block it at the source, but holding the allocation 
  34.  * mutex should be enough. 
  35.  * 
  36.  * In rare circumstances (JNI AttachCurrentThread) we can be called 
  37.  * from a non-VM thread. 
  38.  * 
  39.  * Use ALLOC_DONT_TRACK when we either don't want to track an allocation 
  40.  * (because it's being done for the interpreter "new" operation and will 
  41.  * be part of the root set immediately) or we can't (because this allocation 
  42.  * is for a brand new thread). 
  43.  * 
  44.  * Returns NULL and throws an exception on failure. 
  45.  * 
  46.  * TODO: don't do a GC if the debugger thinks all threads are suspended 
  47.  */  
  48. void* dvmMalloc(size_t size, int flags)  
  49. {  
  50.    void *ptr;  
  51.    
  52.     dvmLockHeap();  
  53.    
  54.     /* Try as hard as possible to allocate some memory. 
  55.      */  
  56.     ptr = tryMalloc(size);  
  57.    
  58.     //do something  
  59.    
  60.     dvmUnlockHeap();  
  61.    
  62.     //do something  
  63.    
  64.    return ptr;  
  65. }  
  66.    
  67. /* Try as hard as possible to allocate some memory. 
  68.  */  
  69. static void *tryMalloc(size_t size)  
  70. {  
  71.     void *ptr;  
  72.      
  73.     ptr = dvmHeapSourceAlloc(size);  
  74.      
  75.     //do something  
  76.    
  77.     /* 
  78.      * The allocation failed.  If the GC is running, block until it 
  79.      * completes and retry. 
  80.      */  
  81.     if (gDvm.gcHeap->gcRunning) {  
  82.         /* 
  83.          * The GC is concurrently tracing the heap.  Release the heap 
  84.          * lock, wait for the GC to complete, and retrying allocating. 
  85.          */  
  86.         dvmWaitForConcurrentGcToComplete();  
  87.     } else {  
  88.       /* 
  89.        * Try a foreground GC since a concurrent GC is not currently running. 
  90.        */  
  91.       gcForMalloc(false);  
  92.     }  
  93.    
  94.    
  95.     //do something  
  96.    
  97.     return NULL;  
  98. }  

到目前会发现在配置内存( dvmHeapSourceAlloc)的时候, 还会在呼叫一个( gcForMalloc)函数, 看似跟GC有关的动作. 先来分析 dvmHeapSourceAlloc函数
  1. // HeapSource.cpp  
  2. /* 
  3.  * Allocates <n> bytes of zeroed data. 
  4.  */  
  5. void* dvmHeapSourceAlloc(size_t n)  
  6. {  
  7.    //检查heap memory是否存在.  
  8.    HS_BOILERPLATE();  
  9.    HeapSource *hs = gHs;  
  10.    Heap* heap = hs2heap(hs);  
  11.    // 检查配置长度 n 是否超过初始化的界线.  
  12.    if (heap->bytesAllocated + n > hs->softLimit) {  
  13.       //do something  
  14.       return NULL;  
  15.    }  
  16.    // 在heap memory中配置一块 n 长度的内存  
  17.    void* ptr = mspace_calloc(heap->msp, 1, n);  
  18.    // do something  
  19.    countAllocation(heap, ptr);  
  20.    // do something  
  21.    return ptr;  
  22. }  
  23.    
  24. static void countAllocation(Heap *heap, const void *ptr)  
  25. {  
  26.     assert(heap->bytesAllocated < mspace_footprint(heap->msp));  
  27.    
  28.     heap->bytesAllocated += mspace_usable_size(ptr) +  
  29.             HEAP_SOURCE_CHUNK_OVERHEAD;  
  30.     heap->objectsAllocated++;  
  31.     HeapSource* hs = gDvm.gcHeap->heapSource;  
  32.     dvmHeapBitmapSetObjectBit(&hs->liveBits, ptr);  
  33.    
  34.     assert(heap->bytesAllocated < mspace_footprint(heap->msp));  
  35. }  
  36.    
  37. // HeapBitmapInlines.h  
  38. /* 
  39.  * Sets the bit corresponding to <obj>, and widens the range of seen 
  40.  * pointers if necessary.  Does no range checking. 
  41.  */  
  42. static void dvmHeapBitmapSetObjectBit(HeapBitmap *hb, const void *obj)  
  43. {  
  44.     _heapBitmapModifyObjectBit(hb, obj, truefalse);  
  45. }  
  46.    
  47. /* 
  48.  * Internal function; do not call directly. 
  49.  */  
  50. static unsigned long _heapBitmapModifyObjectBit(HeapBitmap *hb, const void *obj,  
  51.                                                 bool setBit, bool returnOld)  
  52. {  
  53.     const uintptr_t offset = (uintptr_t)obj - hb->base;  
  54.     const size_t index = HB_OFFSET_TO_INDEX(offset);  
  55.     const unsigned long mask = HB_OFFSET_TO_MASK(offset);  
  56.    
  57.     assert(hb->bits != NULL);  
  58.     assert((uintptr_t)obj >= hb->base);  
  59.     assert(index < hb->bitsLen / sizeof(*hb->bits));  
  60.     if (setBit) {  
  61.         if ((uintptr_t)obj > hb->max) {  
  62.             hb->max = (uintptr_t)obj;  
  63.         }  
  64.         if (returnOld) {  
  65.             unsigned long *p = hb->bits + index;  
  66.             const unsigned long word = *p;  
  67.             *p |= mask;  
  68.             return word & mask;  
  69.         } else {  
  70.             hb->bits[index] |= mask;  
  71.         }  
  72.     } else {  
  73.         hb->bits[index] &= ~mask;  
  74.     }  
  75.     return false;  
  76. }  
由上面的程序代码可以知道, dvmHeapSourceAlloc 函数除了配置一块长度为n 的内存之外, 还为这块内存设定mask. 方便之后GC做回收机制有个依据. 在此我们做个简单的归纳.

1. 一个Heapmemory管理一个mspace, 此mspace是一块连续可配置的内存.

2. 每当从Heapmemory配置一块内存时, 同时会有另外一块内存(HeapBitmap)来记录在HeapMemory 配置内存的状态.在Heapmemory中所配置的连续内存, 每8 bytes相当于在 HeapBitmap内存中的每一个bite. 也就是说若在Heap memory里离起始点第n个8 byte配置一块内存时, HeapBitmap内存里第n个bite就被设置起来.

继续分析跟GC有关的函数 gcForMalloc

  1. //Heap.cpp  
  2. /* Do a full garbage collection, which may grow the 
  3.  * heap as a side-effect if the live set is large. 
  4.  */  
  5. static void gcForMalloc(bool clearSoftReferences)  
  6. {  
  7.     if (gDvm.allocProf.enabled) {  
  8.         Thread* self = dvmThreadSelf();  
  9.         gDvm.allocProf.gcCount++;  
  10.         if (self != NULL) {  
  11.             self->allocProf.gcCount++;  
  12.         }  
  13.     }  
  14.     /* This may adjust the soft limit as a side-effect. 
  15.      */  
  16.     const GcSpec *spec = clearSoftReferences ? GC_BEFORE_OOM :  
  17.                       GC_FOR_MALLOC;  
  18.     dvmCollectGarbageInternal(spec);  
  19. }  
  20.    
  21. /* 
  22.  * Initiate garbage collection. 
  23.  * 
  24.  * NOTES: 
  25.  * - If we don't hold gDvm.threadListLock, it's possible for a thread to 
  26.  *   be added to the thread list while we work.  The thread should NOT 
  27.  *   start executing, so this is only interesting when we start chasing 
  28.  *   thread stacks.  (Before we do so, grab the lock.) 
  29.  * 
  30.  * We are not allowed to GC when the debugger has suspended the VM, which 
  31.  * is awkward because debugger requests can cause allocations.  The easiest 
  32.  * way to enforce this is to refuse to GC on an allocation made by the 
  33.  * JDWP thread -- we have to expand the heap or fail. 
  34.  */  
  35. void dvmCollectGarbageInternal(const GcSpec* spec)  
  36. {  
  37.     //do something  
  38.    
  39.     // suspend all thread  
  40.     dvmSuspendAllThreads(SUSPEND_FOR_GC);  
  41.    
  42.     dvmMethodTraceGCBegin();  
  43.     /* Set up the marking context. 
  44.      */  
  45.     if (!dvmHeapBeginMarkStep(spec->isPartial)) {  
  46.         LOGE_HEAP("dvmHeapBeginMarkStep failed; aborting");  
  47.         dvmAbort();  
  48.     }  
  49.     /* Mark the set of objects that are strongly reachable from the roots. 
  50.      */  
  51.     dvmHeapMarkRootSet();  
  52.     /* dvmHeapScanMarkedObjects() will build the lists of known 
  53.      * instances of the Reference classes. 
  54.      */  
  55.     assert(gcHeap->softReferences == NULL);  
  56.     assert(gcHeap->weakReferences == NULL);  
  57.     assert(gcHeap->finalizerReferences == NULL);  
  58.     assert(gcHeap->phantomReferences == NULL);  
  59.     assert(gcHeap->clearedReferences == NULL);  
  60.     /* Recursively mark any objects that marked objects point to strongly. 
  61.      * If we're not collecting soft references, soft-reachable 
  62.      * objects will also be marked. 
  63.      */  
  64.     dvmHeapScanMarkedObjects();  
  65.     /* 
  66.      * All strongly-reachable objects have now been marked.  Process 
  67.      * weakly-reachable objects discovered while tracing. 
  68.      */  
  69.     dvmHeapProcessReferences(&gcHeap->softReferences,  
  70.                              spec->doPreserve == false,  
  71.                              &gcHeap->weakReferences,  
  72.                              &gcHeap->finalizerReferences,  
  73.                              &gcHeap->phantomReferences);  
  74.     //Sweeping...  
  75.     dvmHeapSweepSystemWeaks();     
  76.     /* 
  77.      * Live objects have a bit set in the mark bitmap, swap the mark 
  78.      * and live bitmaps.  The sweep can proceed concurrently viewing 
  79.      * the new live bitmap as the old mark bitmap, and vice versa. 
  80.      */  
  81.     dvmHeapSourceSwapBitmaps();   
  82.     /* 
  83.      * Walk through the list of objects that haven't been marked and free 
  84.      * them.  Assumes the bitmaps have been swapped. 
  85.      */  
  86.     dvmHeapSweepUnmarkedObjects(spec->isPartial, spec->isConcurrent,  
  87.                                 &numObjectsFreed, &numBytesFreed);  
  88.     //Cleaning up...  
  89.     dvmHeapFinishMarkStep();  
  90.      /* Now's a good time to adjust the heap size, since 
  91.      * we know what our utilization is. 
  92.      * 
  93.      * This doesn't actually resize any memory; 
  94.      * it just lets the heap grow more when necessary. 
  95.      */  
  96.     dvmHeapSourceGrowForUtilization();  
  97.     dvmMethodTraceGCEnd();  
  98.     //do something  
  99.     dvmResumeAllThreads(SUSPEND_FOR_GC);  
  100.     //do something  
  101. }  
最后由上面的程序代码可以知道 dvmCollectGarbageInternal 函数做了很多事, 粗体化的函数跟资源回收有关, 这些函数的功能归纳如下:

1.  suspend 此程序里所有的thread.

2.  初始化一个 Mark Stack用来作为追踪HeapBitmap中的bitmark.

3.  从root开始检查有强可及的对象都做个标记. 检查的地方如下:

    - System classes defined by rootclassloader

    - Foreach thread:

    -Interpreted stack, from top to "curFrame"

    -Dalvik registers (args + local vars)

    - JNIlocal references

    -Automatic VM local references (TrackedAlloc)

    -Associated Thread/VMThread object

    -ThreadGroups (could track & start with these instead of working upward from

      Threads)

    -Exception currently being thrown, if present

  - JNIglobal references

  -Interned string table

  -Primitive classes

  -Special objects

    -gDvm.outOfMemoryObj

  -Objects in debugger object registry

4.     将在Heapmemory中的所有的对象只要不是被soft reference 或是 weakreference 所参考, 全部都做个标记且在bitmapmemory中的位作设定. 并且将对象推进Mark Stack.

5.     开始处理heapmemory中的所有soft reference 跟 weakreference, 将这些的reference全部都设为NULL, 使其可及对象失去参考对象.

6.     将所有在Heapmemory中没被标记的系统对象全部回收.

7.     活动对象在markbitmap中有一个位设定, 就将livebitmap 跟 mark bitmap 互换. 反之亦然. 将有标记跟没标记的活动对象作分类.

8.     开始走访bitmapmemory检查位, 将有设定的位跟未设定的位取出来, 来找出未标记的对象并做回收.

9.     将bitmapmemory里的位全部从新初始化, 且删除MarkStack.

10.   利用HeapSource从新调整Heap memory size.

11.   Resume 此程序里所有的thread.

Conclusion

        由前面的分析可以归纳一下AndroidDVM 的内存管理是如何处理资源回收机制. 在android 一开机的时候就开始处理DVM的初始化, 在这初始化中, 做三件事.

1.     划分一块mSpace 的内存区域.

2.     在这个mSpace 内存区域中配置一块Heap memory, 由Heapsource来设定此块内存的属性. 且配置一块Bitmap memory来记录此Heap memory的状态.

3.     另外配置一块mark stack memory来存放所配置的对象.

当java程序需要实体化一个对象时, 其流程会从dvmMalloc函数开始. 一开始便是一旦在Heapmemory中配置了一块内存就会在Heap memory中的BitmapMemory中去设定位. 之后再由gcForMalloc去执行回收机制, 其回收机制就利用对象的标记与否来判定是否要回收. 在分析中有提到强可及对象,java的语法中只要一般参考指向new出来的对象,这个参考就称为强参考或是强引用,而相对的对象就叫强可及物件.一旦参考若在程序某处被指定为NULL或是指向别的对象,此时原本所指的对象就退化为软可及物件.  强可及对象跟软可及对象是跟被指向的参考有关, Java的参考有分强, 软, 弱, 虚四种参考之分, 这是属于另外一个topic, 在网络上有很多高手在讨论. AndroidDVM 内存管理就分析到此为止, 这里只是把重点点了出来, 想要更了解详细作法还是需要搭配程序代码来研究.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值