拯救OOM!字节自研 Android 虚拟机内存管理优化黑科技 mSponge

本文介绍了字节跳动自研的Android虚拟机内存管理优化方案mSponge,旨在解决OOM问题。通过关键实现,包括获取LargeObjectMapSpace内存、从虚拟机中移除LargeObjectSpace内存以及内存校验,实现了在内存不足时动态调整内存统计,以扩大其他内存空间的使用上限。mSponge二期方案通过监听和拦截OOM异常,按需开启内存优化,确保内存申请成功。
摘要由CSDN通过智能技术生成
4.3.2 流程示意

b0206e19441ac40ec87854896e1a4276.png

LargeObjectMapSpace申请的内存,直接通过 Map 映射到虚拟内存,因此对于 32 位环境应用空间可映射内存在 3G 左右,但虚拟机本身会抢先占用 1G+的地址空间用于管理 Java 内存,因此应用侧实际使用范围在 2G 左右,极端情况下调整后的虚拟机内存理论范围将在 512M~2.5G,至于下限为何是 512M?理论上如果发生 OOM 时虚拟机没有任何大对象,这种情况下,则虚拟机可用内存范围将保持不变,因为我们改变的 Java 大对象的内存可用空间;示意图如下:

f34f680a547ea7e617af1866004501a8.png

4.3.3 关键实现

上面介绍了该方案的背景知识和实现思路,接下来就要从技术层面考虑如何去实现了。如果在系统层面,直接从源码层面定制,相关改动会轻松很多,但是对应用侧来说,要想兼容不同 Android 版本,只有一条路可走——通过 InlineHook 代理相关接口,在执行过程中魔改相关参数以达到目的。在解决完接口代理问题之后,接下来还有下面几件事情要解决:

  • 虚拟机并没有对外暴露获取 LargeObjectMapSpace 内存的接口,如何才能实时获取当前 Space 已申请的内存大小?

  • 如何在合适的时机同步 Heap::num_bytes_allocated_内存统计,以便于让 LargeObjectMapSpace 的内存"脱离"虚拟机的统计?

  • 如何"跳过"虚拟机在内存释放过程对内存大小一致性校验的问题?

4.3.3.1 获取 LargeObjectMapSpace 当前内存

针对第一个问题,尽管 LargeObjectSpace 中提供了获取当前内存大小的接口(LargeObjectSpace::GetBytesAllocated),但是这个接口并没有对外暴露,因此需要通过解析 Libart.so 中的"GetBytesAllocated"符号,以 Android Q 为例,该函数签名符号为:_ZN3art2gc5space16LargeObjectSpace17GetBytesAllocatedEv;并在运行过程中动态获取该符号在内存中的地址。

由于 GetBytesAllocated 是非静态函数,因此在实际调用该接口时,需要知道当前对象的实例化对象,然后通过实例化对象调用该接口即可,在这里,我们通过 inlineHook 代理"LargeObjectMapSpace::Alloc"获取 LargeObjectMapSpace 的实例,LargeObjectMapSpace::Alloc 接口部分源码如下:

mirror::Object* LargeObjectMapSpace::Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated, size_t* usable_size, size_t* bytes_tl_bulk_allocated) {

std::string error_msg;

MemMap mem_map = MemMap::MapAnonymous(“large object space allocation”,

num_bytes,

PROT_READ | PROT_WRITE,

/low_4gb=/ true,

&error_msg);

//申请成功后将当前内存占用+ allocation_size

num_bytes_allocated_  += allocation_size ;

total_bytes_allocated_ += allocation_size;

++ num_objects_allocated_  ;  //申请成功后将当前内存数量+1

++total_objects_allocated_;

return obj;

}

在获取 LargeObject

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值