当前位置:网站首页>内存泄漏之KOOM
内存泄漏之KOOM
2022-06-24 03:34:00 【赵健zj】
资料
Hprof Agent
KOOM
Hprof
android中hprof文件分析
快照技术(COW与ROW技术)
Android内存泄漏简介
关于Hprof的方方面面
内存性能分析器中的泄漏检测
分析应用性能
使用内存性能分析器查看应用的内存使用情况
管理应用内存
Android开发之——Profiler-内存分析
/proc/self/status讲解
Linux EUID,SUID,RUID简单理解
Linux:/proc/meminfo参数详细解释
读取Android设备的内存数据- USS,PSS,RSS
Debug
Linux内存那些事 – VSS、RSS、PSS、USS
Linux 进程内存使用统计VSS RSS PSS USSS
Andorid9.0和10.0下的的libart.so
Hprof文件分析
Hprof最初是由J2SE支持的一种二进制堆转储格式,hprof文件保存了当前java堆上所有的内存使用信息,能够完整的反映虚拟机当前的内存状态。
Hprof文件由FixedHead和一系列的Record组成,Record包含字符串信息、类信息、栈信息、GcRoot信息、对象信息。每个Record都是由1个字节的Tag、4个字节的Time、4个字节的Length和Body组成,Tag表示该Record的类型,Body部分为该Record的内容,长度为Length。
Android中的Hprof

管理应用内存
继承ComponentCallbacks2接口,并onTrimMemory中回调
您的应用可以在处于前台或后台时监听与内存相关的事件,然后释放对象以响应指示系统需要回收内存的应用生命周期事件或系统事件。
import android.content.ComponentCallbacks2;
public class MainActivity extends AppCompatActivity
implements ComponentCallbacks2 {
/** * Release memory when the UI becomes hidden or when system resources become low. * @param level the memory-related event that was raised. */
public void onTrimMemory(int level) {
// Determine which lifecycle or system event was raised.
switch (level) {
case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
/* Release any UI objects that currently hold memory. The user interface has moved to the background. */
break;
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
/* Release any memory that your app doesn't need to run. The device is running low on memory while the app is running. The event raised indicates the severity of the memory-related event. If the event is TRIM_MEMORY_RUNNING_CRITICAL, then the system will begin killing background processes. */
break;
case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
/* Release as much memory as the process can. The app is on the LRU list and the system is running low on memory. The event raised indicates where the app sits within the LRU list. If the event is TRIM_MEMORY_COMPLETE, the process will be one of the first to be terminated. */
break;
default:
/* Release any non-critical data structures. The app received an unrecognized memory level value from the system. Treat this as a generic low-memory message. */
break;
}
}
}
查看您应该使用多少内存
private String getAvailableMemory() {
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
StringBuilder sb = new StringBuilder();
sb.append("availMem = ").append(memoryInfo.availMem).append("\n")
.append("totalMem = ").append(memoryInfo.totalMem).append("\n")
.append("threshold = ").append(memoryInfo.threshold).append("\n")
.append("lowMemory = ").append(memoryInfo.lowMemory).append("\n");
return sb.toString();
}
怎么引发内存泄漏
Android中的泄漏对象
判断一个对象是否泄漏首先要判断该对象是否不再使用,想要判断这一点则需要对象有明显的生命周期,在Android中有以下对象可以判断是否泄漏:
- 1、Activity: 通过Activity的mDestroyed属性来判断该Activity是否已经销毁,如果已经销毁且未被回收则认为是泄漏
Fragment: 通过Fragment的mFragmentManager是否为空来判断该Fragment是否处于无用状态,如果mFragmentManager为空且未被回收则认为是泄漏。 - 2、View: 通过unwrapper mContext获得Activity,如果存在Activity,则判断该Activity是否泄漏。
Editor: Editor指的是android.widget包下的Editor,是用于TextView处理editable text的辅助类,通过mTextView是否为空来判断Editor是否处于无用状态,如果mTextView为空且未被回收则认为是泄漏。 - 3、ContextWrapper: 通过unwrapper ContextWrapper获得Activity,如果存在Activity,则判断该Activity是否泄漏。
- 4、Dialog: 通过mDecor是否为空判断该Dialog是否处于无用状态,如果mDecor为空且未被回收则认为是泄漏。
- 5、MessageQueue: 通过mQuitting或者mQuiting(应该是历史原因,前期拼写错误为mQuiting,后来改正)来判断MessageQueue是否已经退出,如果已经退出且未被回收则认为是泄漏。
- ViewRootImpl: 通过ViewRootImpl的mView是否为空来判断该ViewRootImpl是否处于无用状态,如果mView为空且未被回收则认为是泄漏。
- 6、Window: 通过mDestroyed来判断该Window是否处于无用状态,如果mDestroyed为true且未被回收则认为是泄漏。
Toast: 拿到mTN,通过mTN的mView是否为空来判断当前Toast是否已经hide,如果已经hide且未被回收则认为是泄漏。
泄漏的形式
泄漏的形式
泄漏的本质就是无用对象被持有导致无法回收,具体的形式有如下几种:
- 1、非静态内部类、匿名内部类持有外部类对象引用: 一般为用于回调的Listener,该Listener被别的地方持有,间接导致外部类对象被泄漏。
- 2、Handler: 在Activity中定义Handler对象的时候,Handler持有Activity同时Message持有Handler,而Message被MessageQueue持有,最终导致Activity泄漏。
- 3、资源对象未关闭: 数据库连接、Cursor、IO流等使用完后未close。
- 4、属性动画: 使用ValueAnimator和ObjectAnimator的时候,未及时关闭动画导致泄漏。Animator内部向AnimationHandler注册listener,AnimationHandler是一个单例,如果不及时cancel,会导致Animator泄漏,间接导致Activity/Fragment/View泄漏(比如Animator的updateListener一般都以匿名内部类实现)
- 5、逻辑问题: 注册监听器之后未及时解注册,比如使用EventBus的时候没有在合适的时候进行解注册
Profiler的使用
内存性能分析器Profiler概览

- 捕获堆转储(Capture heap dump):查看应用程序中在特定时间点使用内存的对象
- 记录Native分配(Record native allocations):查看每个C/C++对象在一段时间内是如何分配的
- 记录java/kotlin分配(Record java/kotlin allocations):查看在一段时间内如何分配每个java/kotlin对象

Heap分区

- app heap:当前APP从堆中分配的内存
- image heap:系统启动映像,包含启动期间预加载的类。此处的分配保证绝不会移动或消失
- zygote heap:zygote是所有APP进程的母进程,linux的进程使用COW技术,所有的APP共享zygote的内存空间,因此堆的话也继承了,并且zygote的这些空间不允许写入,为了加快java的启动和运行速度,zygote在启动时预加载了许多资源和代码,这样可以提高APP的运行效率。
源码
- zygote heap:zygote是所有APP进程的母进程,linux的进程使用COW技术,所有的APP共享zygote的内存空间,因此堆的话也继承了,并且zygote的这些空间不允许写入,为了加快java的启动和运行速度,zygote在启动时预加载了许多资源和代码,这样可以提高APP的运行效率。
enum HprofHeapId {
HPROF_HEAP_DEFAULT= 0,
HPROF_HEAP_ZYGOTE= 'Z',
HPROF_HEAP_APP= 'A',
HPROF_HEAP_IMAGE= 'I',
};
if (space->IsZygoteSpace()) {
heap_type= HPROF_HEAP_ZYGOTE;
VisitRoot(obj, RootInfo(kRootVMInternal));
} else if (space->IsImageSpace() && heap->ObjectIsInBootImageSpace(obj)) {
// Only countobjects in the boot image as HPROF_HEAP_IMAGE, this leaves app image objects as
// HPROF_HEAP_APP.b/35762934
heap_type= HPROF_HEAP_IMAGE;
VisitRoot(obj, RootInfo(kRootVMInternal));
}
} else {
const auto* los = heap->GetLargeObjectsSpace();
if (los->Contains(obj) && los->IsZygoteLargeObject(Thread::Current(), obj)) {
heap_type= HPROF_HEAP_ZYGOTE;
VisitRoot(obj, RootInfo(kRootVMInternal));
}
Instance View

Depth
depth是从gc roots到选中的当前对象的引用链最短长度。在java垃圾回收机制中,被gc roots引用到的对象不会被回收。如下图:在gc root 引用树之外的对象会被回收。
Android中gc root主要分为下面几类:
Native Size
Native Size对象的内存大小,这个值只有在Android 7.0以及更高的版本可见。
Shallow Size
对象本身占用的内存,不包括它引用的其它实例。
Shallow Size = [类定义] + 父类fields所占空间 + 自身fields所占空间 + [alignment]
Retained Size
Retained Size是指,当实例A被回收时,可以同时被回收的实例的Shallow Size之和,所以进行内存分析时,应该重点关注Retained Size较大的实例;或者可以通过Retained Size判断出某A实例内部使用的实例是否被其它实例引用。

Reference
Reference里面主要是类的引用关系,可以通过引用关系,一层一层的查看类是如何泄漏的
KOOM
KOOM的整体依赖图

无主动出发GC不卡顿

启动服务之前创建的Intent传参
REASON=reanalysis
THREAD=714
JAVA_MAX_MEM=192.0
USAGE_TIME=5
DEVICE_AVA_MEM=3476.6563
CURRENT_PAGE=javaleak.JavaLeakTestActivity
RESULT_RECEIVER=com.kwai.koom.javaoom.monitor.analysis.[email protected]f003f7
FD=32
PSS=62.92871mb
RSS=91.58594mb
SDK=23
VSS=1643.3594mb
TIME=2022-06-19_21-09-10_345
MODEL=MuMu
JAVA_USED_MEM=12.838821
HPROF_FILE=/storage/emulated/0/Android/data/com.kwai.koom.demo/files/performance/oom/memory/hprof-aly/1.0.0_2022-06-19_21-00-03_901.hprof
DEVICE_MAX_MEM=3953.0703
MANUFACTURE=Netease
JSON_FILE=/storage/emulated/0/Android/data/com.kwai.koom.demo/files/performance/oom/memory/hprof-aly/1.0.0_2022-06-19_21-00-03_901.json
ROOT_PATH=/storage/emulated/0/Android/data/com.kwai.koom.demo/files/performance/oom
HeapGraph

JavaHeap(内存使用信息)
JavaHeap(max=402653184, total=27552536, free=20674832, used=6877704, rate=0.017080963)
data class JavaHeap(
var max: Long = 0, // Runtime.getRuntim().maxMemory()
var total: Long = 0, // Runtime.getRuntime().totalMemory()
var free: Long = 0, // Runtime.getRuntime().freeMemory()
var used: Long = 0, // javaHeap.total - javaHeap.free
var rate: Float = 0f // 1.0f * javaHeap.used / javaHeap.max
)
ProcStatus
ProcStatus(thread=731, vssInKb=18421872, rssInKb=138368)
data class ProcStatus(var thread: Int = 0, var vssInKb: Int = 0, var rssInKb: Int = 0)
[email protected] KOOM % adb shell
HWANA:/ $ cat /proc/self/status
Name: cat // 应用程序或命令的名字
Umask: 0000
State: R (running) // 任务的状态,运行/睡眠/僵死
Tgid: 30578 // 线程组号
Ngid: 0
Pid: 30578 // 任务ID进程ID
PPid: 30572 // 父进程ID
TracerPid: 0 // 接受跟踪该进程信息的ID号
Uid: 2000 2000 2000 2000 (Uid euid suid fsuid)
Gid: 2000 2000 2000 2000 (Gid eguid sgid fsgid)
FDSize: 64 // 文件描述符的最大个数,file->fds
Groups: 1004 1007 1011 1015 1028 3001 3002 3003 3006 3009 3011
VmPeak: 31132 kB
VmSize: 30232 kB // 任务虚拟地址空间的大小 (total_vm-reserved_vm),其中total_vm为进程的地址空间的大小,reserved_vm:进程在预留或特殊的内存间的物理页
VmLck: 0 kB // 任务已经锁住的物理内存的大小。锁住的物理内存不能交换到硬盘(locked_vm)
VmPin: 0 kB
VmHWM: 3160 kB
VmRSS: 3140 kB // 应用程序正在使用的物理内存的大小,就是用ps命令的参数rss的值(rss)。
RssAnon: 600 kB
RssFile: 2360 kB
RssShmem: 180 kB
VmData: 4904 kB // 程序数据段的大小(所占虚拟内存的大小),存放初始化了的数据;(total_vm-shared_vm-stack_vm)
VmStk: 136 kB // 任务在用户态的栈的大小(stack_vm)
VmExe: 432 kB // 程序所拥有的可执行虚拟内存的大小,代码段,不包括任务使用的库(end_code-start_code)
VmLib: 3156 kB // 被映像到任务的虚拟内存空间的库的大小(exec_lib)
VmPTE: 48 kB // 该进程的所有页表的大小,单位kb。Threads共享使用该信号描述符任务的个数,在POSIX多线程应用程序中,线程组中的所有线程使用同一个信号描述符。
VmPMD: 12 kB //
VmSwap: 0 kB
Threads: 1 //
SigQ: 0/25471 // 待处理信号的个数
SigPnd: 0000000000000000 // 屏蔽位,存储了该线程的待处理信号
ShdPnd: 0000000000000000 // 屏蔽为,存储了该线程组的待处理信号
SigBlk: 0000000080000000 // 存放被阻塞的信号
SigIgn: 0000000000000000 // 存放被忽略的信号
SigCgt: 0000000c400084f8 // 存放被俘获到的信号
CapInh: 0000000000000000 //
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 00000000000000c0
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 0
Speculation_Store_Bypass: thread vulnerable
Cpus_allowed: ff
Cpus_allowed_list: 0-7
Mems_allowed: 1
Mems_allowed_list: 0
voluntary_ctxt_switches: 0
nonvoluntary_ctxt_switches: 1
MemInfo

data class MemInfo(
var totalInKb: Int = 0,
var freeInKb: Int = 0,
var availableInKb: Int = 0,
var IONHeap: Int = 0,
var cmaTotal: Int = 0,
var rate: Float = 0f
)
PD1728:/ $ cat /proc/meminfo
MemTotal: 5839880 kB // 可供kernel支配的内存
MemFree: 436760 kB // 表示系统尚未使用的内存
MemAvailable: 2830796 kB // 内核使用特定的算法估算出来的,不精确
Buffers: 145848 kB //
Cached: 2336296 kB
SwapCached: 10448 kB
Active: 1849328 kB
Inactive: 1849508 kB
Active(anon): 886964 kB
Inactive(anon): 333128 kB
Active(file): 962364 kB
Inactive(file): 1516380 kB
Unevictable: 3592 kB
Mlocked: 3592 kB
SwapTotal: 2097148 kB
SwapFree: 587260 kB
Dirty: 96 kB
Writeback: 0 kB
AnonPages: 1216292 kB
Mapped: 882444 kB
Shmem: 780 kB
Slab: 365740 kB
SReclaimable: 133356 kB
SUnreclaim: 232384 kB
KernelStack: 85952 kB
PageTables: 112180 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 5017088 kB
Committed_AS: 153060520 kB
VmallocTotal: 258867136 kB
VmallocUsed: 0 kB //
VmallocChunk: 0 kB
CmaTotal: 176128 kB
CmaFree: 8076 kB
PD1728:/ $
hprofStringCache
hprofStringCache first->4224708 , second->accessibility_custom_action_22
hprofStringCache first->4203524 , second->taskAffinity
hprofStringCache first->4208309 , second->Theme_textAppearanceEasyCorrectSuggestion
hprofStringCache first->4199920 , second->AndroidManifestActivity_enabled
hprofStringCache first->4205019 , second->TRANSACTION_partitionMixed
hprofStringCache first->4220338 , second->mOnPreparedListener
hprofStringCache first->4227170 , second->androidx.appcompat.view.ViewPropertyAnimatorCompatSet
hprofStringCache first->4219142 , second->m_version_
hprofStringCache first->4219707 , second->secprops
hprofStringCache first->4194621 , second->dalvik.system.CloseGuard$DefaultReporter
hprofStringCache first->4197531 , second->endTime
hprofStringCache first->4204476 , second->LINECAP_ROUND
hprofStringCache first->4199289 , second->id_aa_ets_contentTimestamp
hprofStringCache first->4219711 , second->ABASE
hprofStringCache first->4219795 , second->tomorrow
hprofStringCache first->4212952 , second->ACQUIRE_CAUSES_WAKEUP
hprofStringCache first->4214386 , second->defaultUncaughtHandler
hprofStringCache first->4210042 , second->mCurSurfaceHolder
hprofStringCache first->4195686 , second->roundingIncrement
hprofStringCache first->4217322 , second->mFpsNumFrames
hprofStringCache first->4202630 , second->android.app.Fragment
hprofStringCache first->4217865 , second->EXTRA_CONNECTION_STATE
hprofStringCache first->4217949 , second->CHUNK_THST
hprofStringCache first->4207631 , second->INDEX_CENTER_VERTICAL
hprofStringCache first->4207766 , second->CENTER_INSIDE
边栏推荐
- Use lightweight application server to automatically download and upload to onedrive
- Summary of common problems of real-time audio and video TRTC - quality
- Double 11 will arrive soon. Is your website ready?
- Grp: how to gracefully shutdown a process?
- Ligature in font design
- Chapter 5: key led demo case of PS bare metal and FreeRTOS case development
- What if the computer audio and video engine is abnormal? What are the causes of abnormal computer audio and video engine?
- Summary of common SSH commands
- How to select a cloud game server? Which cloud game server recommends?
- Tencent location service appeared at the 11th China Surveying and mapping Geographic Information Technology Equipment Expo
猜你喜欢

Get to know MySQL database

QT creator tips

元气森林推“有矿”,农夫山泉们跟着“卷”?

Community pycharm installation visual database

Sorting out of key vulnerabilities identified by CMS in the peripheral management of red team (I)

Ar 3D map technology

On Sunday, I rolled up the uni app "uview excellent UI framework"

618大促:手机品牌“神仙打架”,高端市场“谁主沉浮”?
![[summary of interview questions] zj6 redis](/img/4b/eadf66ca8d834f049f3546d348fa32.jpg)
[summary of interview questions] zj6 redis
Thank you for your recognition! One thank-you note after another
随机推荐
Actual combat | how to use micro build low code to realize tolerance application
What is the all-in-one backup machine? How about its cost performance
Applicationclientprotocol of yarn source code
Why use code signing? What certificates are required for code signing?
Dry goods how to build a data visualization project from scratch?
How to register a trademark? What needs to be prepared?
What is an edge calculator? How is the unit price of the edge calculator calculated?
web渗透测试----5、暴力破解漏洞--(7)MYSQL密码破解
Tke accesses the cluster through kubectl in pod
Thank you for your recognition! One thank-you note after another
Case analysis | interpret the truth that multi branch enterprises choose sd-wan network reconstruction in combination with real cases
How does the fortress machine connect to the server? Which is easy to use, fortress machine or firewall?
What does cloud desktop mean? What are the characteristics of cloud desktop?
Tencent location service appeared at the 11th China Surveying and mapping Geographic Information Technology Equipment Expo
How the new operator works
What port does the fortress machine use? What is the role of the fortress machine?
[competition experience sharing] design of intelligent guide rod
Clickhouse optimize table comprehensive analysis
Why can't the fortress machine log in? What are the ways to solve the problem
Coding Ci of Devops