一.内存分配
1.内存结构
创建进程分配内存块
内存块中有堆,栈,静态存储区
静态存储区,存放静态数据,全局static数据和常量;
堆,存放对象;
栈,当进程中创建了线程,分给线程一个栈,用于存放局部变量;
函数开始执行时,局部变量的存储单元在栈上创建,当函数执行结束,释放这些存储单元;
堆是不连续的,堆的空间比较大,
栈是连续的内存区域,空间比较小
问题:
1)如何给成员变量分配内存?
成员变量全部存储于堆中(包括基本数据类型,对象引用和引用指向的对象实体),因为它们属于类;
2)int i= 1; 1存放在哪里?
2.内存分配的流程
1)申请内存;
2)申请成功,结束;申请失败,GC,再次申请;
3)申请成功,结束;申请失败,增加堆的大小,再次申请;
4)申请成功,结束;申请失败,GC,再次申请;
5)申请成功,结束;申请失败,OOM;
void* dvmMalloc(size_t size, int flags)
{
void *ptr;
dvmLockHeap();
/* Try as hard as possible to allocate some memory.
*/
ptr = tryMalloc(size);
if (ptr != NULL) {
/* We've got the memory.
*/
if (gDvm.allocProf.enabled) {
Thread* self = dvmThreadSelf();
gDvm.allocProf.allocCount++;
gDvm.allocProf.allocSize += size;
if (self != NULL) {
self->allocProf.allocCount++;
self->allocProf.allocSize += size;
}
}
} else {
/* The allocation failed.
*/
if (gDvm.allocProf.enabled) {
Thread* self = dvmThreadSelf();
gDvm.allocProf.failedAllocCount++;
gDvm.allocProf.failedAllocSize += size;
if (self != NULL) {
self->allocProf.failedAllocCount++;
self->allocProf.failedAllocSize += size;
}
}
}
dvmUnlockHeap();
if (ptr != NULL) {
/*
* If caller hasn't asked us not to track it, add it to the
* internal tracking list.
*/
if ((flags & ALLOC_DONT_TRACK) == 0) {
dvmAddTrackedAlloc((Object*)ptr, NULL);
}
} else {
/*
* The allocation failed; throw an OutOfMemoryError.
*/
throwOOME();
}
return ptr;
}
static void *tryMalloc(size_t size)
{
void *ptr;
......
ptr = dvmHeapSourceAlloc(size);
if (ptr != NULL) {
return ptr;
}
if (gDvm.gcHeap->gcRunning) {
......
dvmWaitForConcurrentGcToComplete();
} else {
......
gcForMalloc(false);
}
ptr = dvmHeapSourceAlloc(size);
if (ptr != NULL) {
return ptr;
}
ptr = dvmHeapSourceAllocAndGrow(size);
if (ptr != NULL) {
......
return ptr;
}
gcForMalloc(true);
ptr = dvmHeapSourceAllocAndGrow(size);
if (ptr != NULL) {
return ptr;
}
......
return NULL;
}
3.Android的内存分配
1)Dalvik虚拟机的内存分配
2)ART的内存分配
二.内存回收-GC
1.Java的GC
GC针对的是堆内存;
GC的步骤:
1)寻找应该回收的对象;
2)回收对象;
GC算法:
1) 引用计数
2)标记-清除
3)标记-清除-压缩
4)复制
5)增量
6)分代
GC-Roots:程序的主要运行对象,如静态对象/寄存器/栈上指向的内存对象等;
GC-Root可达:从GC-Root开始,通过所持有引用的可以获取到的对象是GC-Root可达的,
剩下的对象是GC-Root不可达的,是GC回收的对象;
2.Android的GC
三.内存问题
内存使用不合理引发的问题:
1.OOM
2.GC过多,影响程序的运行
内存使用不合理
1.内存泄漏
1)GC-Root持有对象的引用,static,final;
2)线程持有对象的引用,造成对象的生命周期同线程的生命周期相同;
3)内部类持有外部类的引用,造成外部类的对象的生命周期与内部类的对象生命周期相同;
2.内存占用较大的对象
1)Bitmap
四.内存检测工具
1.Heap Viewer
2.Allocation