Hprof基本概念

hprof最初是由J2SE支持的一种二进制堆转储格式,hprof文件保存了当前java堆上所有的内存使用信息,能够完整的反映虚拟机当前的内存状态。
Hprof文件由FixedHead和一系列的Record组成,Record包含字符串信息、类信息、栈信息、GcRoot信息、对象信息。每个Record都是由1个字节的Tag、4个字节的Time、4个字节的Length和Body组成,Tag表示该Record的类型,Body部分为该Record的内容,长度为Length。
 

生成Hprof文件方式

monkey指令:
adb shell monkey -p com.lion.appfwk.navi -p xxxx –ignore-crashes –ignore-native-crashes –ignore-timeouts –ignore-security-exceptions –throttle 100 -s 666 -v -v -v 300000
内存数据获取指令:
dumpsys meminfo
hprof文件获取指令:
adb shell am dumpheap com.lion.appfwk.navi /sdcard/Download/navi.hprof

Android中的hprof

在Android设备上,我们可以通过两种方式生成当前进程的hprof文件
 
通过调用Debug.dumpHprofData(String filePath)方法来生成hprof文件
通过执行shell命令adb shell am dumpheap pid /data/local/tmp/x.hprof来生成指定进程的hprof文件到目标目录
 
然而Android平台上的hprof文件和标准Java的hprof定义有一些区别,主要是版本号不一样,而且增加了一些特殊Tag,在art/runtime/hprof/hprof.cc中有如下定义
可以看出Android增加了额外的9个HeapTag,其中比较重要的是HPROF_HEAP_DUMP_INFO。Android上将java堆分为Heap-App、Heap-Image 、Heap-Zygote三块,这个Tag的作用是切换当前的堆,该Tag后面紧跟着一个4个字节的堆id和一个堆名称id。
比如出现一个HPROF_HEAP_DUMP_INFO Record,且该Record表示Heap-Image,那么表示后续所有Record中的类、对象、GCRoot对象均在Heap-Image中存储,直到下一个HPROF_HEAP_DUMP_INFO出现为止。

profiler使用

通过下载hprof文件,解压缩后,直接拖到Android studio中,可以通过Android studio中的profiler工具进行分析,如下图:
1、Heap Dump
1、筛选
左边区域可以通过筛选查看到泄漏的activity或者fragment,在Android中的泄漏主要是activity或者fragment有生命周期的类泄漏。
2、Heap区分
Heap 中主要分为三种:
1、app heap
当前APP从堆中分配的内存
2、image heap
系统启动映像,包含启动期间预加载的类。 此处的分配保证绝不会移动或消失
3、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)); }

2、Instance View

点击heap dump中具体的类,右边就会展示instance view Instance view中主要展示对象相关的信息
 

作者 littlepudding

奇瑞汽车,车载智能语音开发

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注