Skip to content

内存(Memory)

为什么要做内存分析 ? 当内存不足会造成异常(oom,内存分配失败,llk,设备重启等)与卡顿(触发频繁的gc),而出现内存不足的原因有很多比如内存泄漏,为了减少oom与卡顿这个时候就需要分析内存从中找出优化点

虚拟机/引擎

  • Android:art
  • React Native/小程序:quickjs 、v8、hermes、javascriptcore,js引擎如何选型?
  • Flutter:dart vm

术语

引用类型

  • 强可及对象(strongly reachable):可以通过强引用访问的对象。
  • 软可及对象(softly reachable):不是强可及对象,并且能够通过软引用访问的对象。
  • 弱可及对象(weakly reachable):不是强可及对象也不是软可及对象,并且能够通过弱引用访问的对象。
  • 虚可及对象(phantomly reachable):不是强可及对象、软可及对象,也不是弱可及对象,已经结束的,可以通过虚引用访问的对象。

清除:将引用对象的 referent 域设置为 null ,并将引用类在堆中引用的对象声明为可结束的。

Shallow Size:对象自身占用的内存大小,不包括它引用的对象

Retained Size:被GC后Heap上释放的内存大小,即当前对象大小+当前对象可直接或间接引用到的对象的大小总和

outgoing reference(当前对象引用的外部对象):查看对象为什么耗内存,我们看到一个线程池占用了>25mb的内存

ingoing reference(直接引用了当前对象的对象):查看对象被谁引用

gc root对象:

  • 类(方法区静态成员变量引用的对象)
  • 活动的Thread实例
  • 局部变量或者方法参数变量持有的对象(java 虚拟机堆栈 、 本地方法堆栈)
  • JNILocalReference引用的对象
  • JNIGlobalReference引用的对象
  • synchronize关键字用到的对象

分代垃圾算法

大部分的对象都是”朝生夕死”,经过几次gc之后就会被转移到老年代。新生代占内存区域的⅓而老年代占内存区域的⅔,新生代使用MinorGC,老年代使用MajorGC/FullGC回收整块堆

  • 新生代(gc:MinorGC)
  • 采用算法 :标记复制法(浪费预留区域的空间,如果遇到大量存活的对象,就需要频繁复制才能释放少量的空间,所以更适合新生代)
  • 分区:Eden区 、S0区(survivor)、S1区(survivor) 比例为8:1:1,压缩了预留空间,从原来的½到1/10
  • 存活的对象会在S0与S1之间来回移动,并且年龄累加1

  • 老年代(gc:MajorGC)

  • 采用的算法:标记清除算法(遇到大部分需要回收的对象时,执行效率不高;容易产生碎片化) or 标记整理算法(若存在大量存活对象,就需要移动更多的对象来换取少量的空间)

内存指标

  • 内存异常率
  • 内存触顶率:超过最大堆的85%限制,gc就会频繁,容易oom与卡顿

Comments