我们在柱状图中,随便的截取一段,就能产生内存的分析:
我们能够看到一些对象,它总共的个数、大小,我们还可以根据类、包和线程来进行排序。
这些对象,分为可控和不可控两种类型:
- 不可控
一些对象是必然会产生的,是伴随着一些对象的产生而产生,并不是我们直接创建,比如我们必须的创建一个对象,而这个对象的构造函数里面会必然的形成一个 int[]
或 String
或其他,在一般情况下,我们不会去考虑这些 int[]
、String
变量
- 可控
由我们直接的,手动的创建出来,比如通过 new
等声明一个变量,它是在我们程序中直观的表示的出来的。
在上面的图片中,我们随便点击一个对象,如果这个对象是可控的,那么我们就能追溯到代码中,如下图:
图中,我选取了一个 LinearLayout
(标注1),可以看到LinearLayout在程序中有多个Instance(标注2),也就是说在我们程序中写了很多个LinearLayout出来,然后我们随便点击一个一个,可以看到它创建的代码栈(标注3),然后我们在代码栈中,可以找到我们在程序中创建出来的地方(标注4)。
可以看到我是在一个RecyclerView
的Adapter
里面去new出了一个item,我的每一个Item的构造就是一个LinearLayout,而一个RecyclerView里面是有多个item,这也是为什么,在标注2中显示我在很短的时间里面创建出了这么多的 LinearLayout。
Heap Dump的主要功能就是查看不同的数据类型在内存中的使用情况。
它可以帮助我们找到大对象,也可以通过数据的变化发生内存泄漏。
我们通过点击 Dump Java Heap
或者 Crtl + D
来捕获一段Heap Dump:
可以看到其分析原理也差不多,不过它可以通过点击最左边的图标的保存文件,保存成一个 .hprof
文件,便于我们后面使用MAT工具进行分析。
我们可以看到这个图和之前分析内存那个有点不一样,这个图最右边的 Refernces
表示的是该对象的信息:
- Depth
GC Roots到达该对象的层数。
也就说GC Roots构成的树里面,这个对象在第n层
- Native Size
C/C++层中的内存大小(B)
- Shallow Size
这个对象在Java层中的内存大小(B)
- Retained Size
这个类中所引用到的对象的总大小(B)
分析你的heap,按照一下步骤.
-
浏览
Class Name
列表,看看有没有大量对象存在,并且这些对象你认为是不应该存在的,可能存在内存泄漏的情况. 点击类名可以看到详细的对象信息. -
在这个
Instance View
面板中,点击一个实例References
面板就会显示出来,里面都是使用该Instance的Reference,点击箭头可以看到引用它的所有区域。点击鼠标右键可以选择go to instance
去看到引用该引用的引用,或者jump to source
去看调用的源代码.
======================================