android dalvik vm alloc.docx
- 文档编号:30017116
- 上传时间:2023-08-04
- 格式:DOCX
- 页数:21
- 大小:25.88KB
android dalvik vm alloc.docx
《android dalvik vm alloc.docx》由会员分享,可在线阅读,更多相关《android dalvik vm alloc.docx(21页珍藏版)》请在冰豆网上搜索。
androiddalvikvmalloc
androiddalvikvmalloc(转)
2011-09-12
gagbagecollection:
为了跟踪对象的应用景象,必须知道内存中的对象是否在被应用,这就须要一个标记指导对象是否正在应用,也就是markbits。
一种规划是每个对象有本身相接洽关系的markbits。
还有一种是将对象和markbits分隔,有自力的存放markbits的内存区域。
当你将markbits与对象一路存放的时辰,就会消费更多的缓冲区。
当你将markbits分隔存放的时辰,就能使缓冲区更慎密。
这是从宏观上来看。
android平台上我们必须总要推敲到所有的过程都在一个机能受限的设备上。
有各自自力的过程、每个过程有本身的堆,每个堆本身自力地进行垃圾收集。
GC和共享:
markbits被分隔存放。
这在android上是可行的规划。
这是因为有zygote过程在。
Zygote有本身的堆,这个堆是被共享的,所以若是让markbits分布在zygote堆中,当我们履行GC的时辰,zygote过程就会触及zygote中的页面并使他们变为不共享的,使它们变为dirty的,就会破损设备上的存储体系的机能。
使markbits被分隔存放的另一个益处是因为在大多半景象下过程并不在垃圾收集,事实上我们并不须要分派mark数组除非是在垃圾收集的时辰。
也就是说我们就可以匀出内存运行更多的应用法度。
以上都是关于内存经管整体概况。
在介绍内存经管代码之前先介绍java中关于引用对象的内容。
引用对象封装了指向其它对象的连接。
被指向的对象称为引用目标。
所有引用对象都是抽象的java.lang.Reference类的子类的实例。
Reference类家族图如图所示,包含了三个直接的子类:
SoftReference,WeakReference,PhantomReference。
SoftReference对象封装了对引用目标的“软引用”;WeakReference封装了对引用目标的“弱引用”;而PhantomReference封装了对引用目标的“影子引用。
强引用禁止引用目标被垃圾收集,而软引用、弱引用和影子引用不禁止。
图中默示了一个SoftReference对象。
一旦一个引用对象创建后,它将一向保持到它的引用目标的软引用、弱引用或影子引用,直到它被法度或垃圾收集器清除。
要清除一个引用对象,法度或垃圾收集器只须要调用引用对象的clear()办法。
经由过程清除引用对象,就割断了引用对象的软引用、弱引用或者影子引用。
垃圾收集器可以随便更改不是强可触及的对象的可触及性状况。
若是对可触及性状况的改变有爱好,可以把引用对象和引用队列接洽关系起来。
引用队列是java.lang.ReferenceQueue的一个实例,垃圾收集器在改变可触及性状况时会添加(编入队列)所涉及的引用对象。
如图所示,当垃圾收集决意收集弱可触及对象的时辰,它会清除WeakReference对象(履行WeakRefence的clear办法),可能立即就把这个WeakReference对象参加到它的引用队列中,也可能在某个稍后的某个时候参加。
为了把引用对象参加到它所接洽关系的队列中,垃圾收集器履行它的enqueue办法。
enqueue办法是在超类Reference中定义的,只有在创建引用对象时接洽关系了一个队列、并且仅当对象的enqueue办法第一次履行时,才把引用对象参加到这个队列中。
在不合的景象下,垃圾收集器把软引用、弱引用和影子引用对象参加队列默示三种不合的可触及性状况的转换。
这默示六种可触及状况、状况变更的详情如下所示:
?
强可触及对象可以从根节点不经由过程任何引用对象搜刮到。
对象生命周期从强可触及状况开端,并且只要有根节点或者别的一个强可触及对象引用它,就对峙强可触及状况。
垃圾收集器不会试图收受接管强可触及对象占领的内存空间。
?
软可触及对象不是强可触及的,然则可以从根节点开端经由过程一个或多个(未被清除的)软引用对象触及。
垃圾收受接管器可能收受接管软可触及的对象所占领的内存。
若是产生了,它会清除所有到此软可触及对象的软引用。
当垃圾收集器清除一个和引用队列有接洽关系的软引用对象时,它把该软引用对象参加队列。
?
弱可触及对象既不是强可触及的也不是软可触及的,然则从根节点开端可以经由过程一个或多个(未被清除的)弱引用对象触及。
垃圾收受接管器必须偿还弱可触及对象所占领的内存。
这产生的时辰,它会清除所有到此弱可触及对象的弱引用。
当垃圾收集器清除一个和引用队列有接洽关系的弱引用对象时,它把该弱引用对象参加队列。
?
可复生的对象不是强可触及、软可触及,也不是弱可触及的,然则仍可能经由过程某些终结办法复生到这几种状况之一。
?
影子可触及对象不是强可触及、软可触及,也不是弱可触及的,并且已经断定不会被任何终结办法复生(若是它本身定义了终结办法,它的终结办法已经被运行过了),并且它可以从根结点开端经由过程一个或多个(未被清除的)影子引用对象触及。
一旦某个被影子引用的对象变成影子可触及状况,垃圾收集器立即把该引用对象参加队列。
垃圾收集器从不会清除一个影子引用,所有的影子引用都必须由法度明白地清除。
?
不成触及一个对象不是强可触及、弱可触及,也不是影子可触及,并且它不成复生。
不成触及对象已经筹办好被收受接管了。
垃圾收集器在把软引用对象和弱引用对象参加队列的时辰,是在它们的引用目标分开响应的可触及状况时;而把影子引用对象参加队列是在引用目标进入响应的状况时!
看两段代码。
这两段代码是垃圾收受接管中的可以或许申明引用对象应用的最好示例。
代码段1
代码段2
下面我们深切虚拟机中关于内存分派的代码。
起首介绍一下和内存经管有关的数据布局:
堆的数据布局:
typedefstruct{
mspace*msp;//应用dlmalloc分派的内存,分派啊、开释啊就在这个对象上方
HeapBitmapobjectBitmap;//位图信息1默示强可触及、0默示不是强可触及
size_tabsoluteMaxSize;//堆可以增长到的最大值
size_tbytesAllocated;//已分派的字节数
size_tobjectsAllocated;//已分派的对象数
}Heap;
structHeapSource{
size_targetUtilization;/*下的堆的应用率,取值局限为1..HEAP_UTILIZATION_MAX*/
size_tminimumSize;//分派的堆的最小大小
size_tstartSize;//堆分派的初始大小
size_tabsoluteMaxSize;//容许分派的对增长到的最大尺寸
size_tidealSize;//幻想的堆的最大大小
size_tsoftLimit;//在垃圾收集前容许堆被分派的最大大小
Heapheaps[HEAP_SOURCE_MAX_HEAP_COUNT];//实其实在的堆
size_tnumHeaps;//当前的堆的个数
size_texternalBytesAllocated;//不是归堆本身分派的外项目组配的大小
size_texternalLimit;//容许外项目组配的最大值
boolsawZygote;/*在创建这个HeapSource的时辰是否是zygote模式也就是是否有zygote过程*/
};
typedefstruct{
unsignedlongint*bits;/*由mmap分派的全零初始化过的匿名内存区域*/
size_tbitsLen;//这个位图的大小
uintptr_tbase;//位图对应的对象指针数组的首地址
uintptr_tmax;/*位图应用中的最后一位被设置的对象指针的地址,若是位图全没设置则max
}HeapBitmap;
typedefstruct{
/*从上往下增长的栈*/
constObject**limit;//容许增长到的最低地址
constObject**top;//栈顶
constObject**base;//栈底
}GcMarkStack;
typedefstruct{
HeapBitmapbitmaps[HEAP_SOURCE_MAX_HEAP_COUNT];//存放位图的数组
size_tnumBitmaps;//位图数
GcMarkStackstack;//GC标识表记标帜栈
constvoid*finger;/*onlyusedwhilescanning/recursing.存放地址上限的一个标识表记标帜*/
}GcMarkContext;
structGcHeap{
HeapSource*heapSource;//堆源数据布局,包含了所有的堆和和堆有关的信息
HeapRefTablenonCollectableRefs;//存储一些不成被垃圾收受接管的对象的参考表
LargeHeapRefTable*finalizableRefs;/*存储一些当被垃圾收受接管时须要履行finalize办法的参考表*/
LargeHeapRefTable*pendingFinalizationRefs;/*存储一些须要履行finalize办法的对象的参考表,然则我没有看到在代码里何处往这个表中填入对象*/
Object*softReferences;//软引用对象的列表
Object*weakReferences;//弱引用对象的列表
Object*phantomReferences;//影子引用对象的列表
LargeHeapRefTable*referenceOperations;/*须要被履行clear或者enqueue办法的引用对象的列表*/
Object*heapWorkerCurrentObject;
Method*heapWorkerCurrentMethod;/*若是这两个对象不为空则默示HeapWorker线程正在履行*/
u8heapWorkerInterpStartTime;/*若是heapWorkerCurrentObject非空则默示HeapWorker开端履行这个办法的时候*/
u8heapWorkerInterpCpuStartTime;/*若是heapWorkerCurrentObject非空则默示HeapWorkerCPU开端履行这个办法的时候*/
structtimespecheapWorkerNextTrim;/*下一次裁剪HeapSource的时候*/
GcMarkContextmarkContext;//做标识表记标帜步调中的状况
u8gcStartTime;//GC开端的时候
boolgcRunning;//是否正在GC
enum{SR_COLLECT_NONE,SR_COLLECT_SOME,SR_COLLECT_ALL}softReferenceCollectionState;//GC时软引用对象收受接管几许,一点都不收集?
收受接管一半?
还是全部收受接管?
size_tsoftReferenceHeapSizeThreshold;/*存在几许软引用对象的时辰开端收受接管软引用对象*/
intsoftReferenceColor;/*当软引用收受接管策略为收受接管一半时应用的概率值*/
boolmarkAllReferents;/*若是被设为true则任何软/弱/影子引用对象引用的对象都邑被标识表记标帜,若是设为false则采取通俗的引用收集策略*/
下面都是统计调试跟踪用到的变量不去管它们
#ifDVM_TRACK_HEAP_MARKING
size_tmarkCount;
size_tmarkSize;
#endif
intddmHpifWhen;
intddmHpsgWhen;
intddmHpsgWhat;
intddmNhsgWhen;
intddmNhsgWhat;
#ifWITH_HPROF
boolhprofDumpOnGc;
hprof_context_t*hprofContext;
#endif
};
Dalvikvirtualmachine的与内存经管相干的数据布局关系如图所示。
为什么堆只有三个我想是因为初始化的时辰生成的是一个堆,若是有Zygote过程则生成的时辰又生成一个堆,再从Zygote过程fork新的过程的时辰又生成一个堆,之掉队程就永远对这个堆也就是被称为是当前堆进行操纵,不会再生成新的堆了。
起首看看HeapWorker线程。
它首要做履行对象的终结函数和引用对象的清理和归队工作,下面看它的代码。
staticvoiddoHeapWork(Thread*self)
{
Object*obj;
HeapWorkerOperationop;
intnumFinalizersCalled,numReferencesEnqueued;
numFinalizersCalled=0;
numReferencesEnqueued=0;
while((obj=dvmGetNextHeapWorkerObject(&op))!
=NULL){
Method*method=NULL;
/*Makesuretheobjecthasn""tbeencollectedsince
*beingscheduled.
*/
/*Calltheappropriatemethod(s).
*/
if(op==WORKER_FINALIZE){
numFinalizersCalled++;
method=obj->clazz->vtable[gDvm.voffJavaLangObject_finalize];
callMethod(self,obj,method);
}else{
if(op&WORKER_ENQUEUE){
numReferencesEnqueued++;
callMethod(self,obj,
gDvm.methJavaLangRefReference_enqueueInternal);
}
}
/*LettheGCcollecttheobject.
*/
dvmReleaseTrackedAlloc(obj,self);
}
}
HeapWorker线程的主函数:
staticvoid*heapWorkerThreadStart(void*arg)
{
Thread*self=dvmThreadSelf();
intcc;
/*tellthemainthreadthatwe""reready*/
dvmLockMutex(&gDvm.heapWorkerLock);
gDvm.heapWorkerReady=true;
cc=pthread_cond_signal(&gDvm.heapWorkerCond);
dvmUnlockMutex(&gDvm.heapWorkerLock);
dvmLockMutex(&gDvm.heapWorkerLock);
while(!
gDvm.haltHeapWorker){
structtimespectrimtime;
booltimedwait=false;
/*We""redonerunninginterpretedcodefornow.*/
dvmChangeStatus(NULL,THREAD_VMWAIT);
/*Signalanyonewhowantstoknowwhenwe""redone.*/
cc=pthread_cond_broadcast(&gDvm.heapWorkerIdleCond);
/*Trimtheheapifwewereaskedto.*/
trimtime=gDvm.gcHeap->heapWorkerNextTrim;
if(trimtime.tv_sec!
=0&&trimtime.tv_nsec!
=0){
structtimevalnow;
gettimeofday(&now,NULL);
if(trimtime.tv_sec (trimtime.tv_sec==now.tv_sec&& trimtime.tv_nsec<=now.tv_usec*1000)) { size_tmadvisedSizes[HEAP_SOURCE_MAX_HEAP_COUNT]; /*TheheapmustbelockedbeforetheHeapWorker; *unrollandre-orderthelocks. dvmLockHeap() *willputusinVMWAITifnecessary. Onceit *returns,thereshouldn""tbeanycontentionon *heapWorkerLock. */ dvmUnlockMutex(&gDvm.heapWorkerLock); dvmLockHeap(); dvmLockMutex(&gDvm.heapWorkerLock); memset(madvisedSizes,0,sizeof(madvisedSizes)); dvmHeapSourceTrim(madvisedSizes,HEAP_SOURCE_MAX_HEAP_COUNT); dvmLogMadviseStats(madvisedSizes,HEAP_SOURCE_MAX_HEAP_COUNT); dvmUnlockHeap(); trimtime.tv_sec=0; trimtime.tv_nsec=0; gDvm.gcHeap->heapWorkerNextTrim=trimtime; }else{ timedwait=true; } } /*sleepuntilsignaled*/ if(timedwait){ cc=pthread_cond_timedwait(&gDvm.heapWorkerCond, &gDvm.heapWorkerLock,&trimtime); }else{ cc=pthread_cond_wait(&gDvm.heapWorkerCond,&gDvm.heapWorkerLock); } /*dvmChangeStatus()mayblock; don""tholdheapWorkerLock. */ dvmUnlockMutex(&gDvm.heapWorkerLock); dvmChangeStatus(NULL,THREAD_RUNNING); dvmLockMutex(&gDvm.heapWorkerLock); /*Processanyeventsinthequeue. */ doHeapWork(self); } dvmUnlockMutex(&gDvm.heapWorkerLock); returnNULL; } 下面是显示GC收集的主函数。 voiddvmCollectGarbageInternal(boolcollectSoftReferences) { GcHeap*gcHeap=gDvm.gcHeap; Object*softReferences; Object*weakReferences; Object*phantomReferences; u8now;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- android dalvik vm alloc