android日常开发

android 内存

2019-06-25  本文已影响0人  众少成多积小致巨

1、内存结构

根据VM规范,VM应该被划分为五块区域——即VM栈、堆、方法区、程序计数器、本地方法栈五个部分。如下图所示:

内存结构图

    方法区(Method Area):该区域是所有线程共享的,主要用于存放类的信息,常量、静态变量、即时编译器编译后的代码等。垃圾回收器对这块区域的回收主要是针对常量池和类的卸载。

    java堆(Java Heap):该区域也是所有线程共享的,用于存放对象实例,绝大多数创建的对象都会被存放到这里(除了部分由于逃逸分析而在对外分配的对象,该部分只是在方法体被引用,故被分配到了栈上)。垃圾回收器最主要针对的对象,对这部分的回收效率影响了VM的整体性能。

    本地方法栈(Native Methiod Stack):该区域是每个线程锁独有的,主要用于VM的Native方法。这部分是有VM自行管理,程序员基本上不需要关系该部分。

    VM栈(VM Stack):该区域也是每个线程所独有的,与本地方法栈是类似的,唯一的区别是它为VM执行Java方法服务。该区域主要维护栈针(每调用一个方法,则VM就会创建一个栈针保护当前方法的状态,并将其压入栈中,当被调用的方法完成后,在将其出栈继续执行未完成的方法),有一定的深度,可能会抛出StackOverflowError和OutOfMemoryError。

    程序记数器:该区域也是每个线程所独有的,该区域主要是存放当前执行指令的地址。


2、GC

关于对象不会被回收,业界一共有两种说法?

1 .引用计数算法

2 .对象可达性算法

下面分别说明:

引用计数法的意思是,给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1,当引用失效时就减1,当对象的引用计数器等于0时,就代表对象需要被回收了。这种算法判断对象是否应该被回收时的效率非常高,很多经典案例也都有引用。但是目前,主流的jvm虚拟机都不会使用这种算法,非常重要的一个原因是:这个算法不能解决对象互相引用的问题。怎么解释呢?

比如

A对象和B对象都有字段instance。

如果A.instance=B.instance

并且B.instance=A.instance

这就是互相引用,实际上是无效的引用,但是计数器算法无法判断这个引用无效。

对象可达性算法:

目前主流的虚拟机都在使用这种算法来判断一个对象是否需要被回收。包括我们比较常见的HotSpot虚拟机。

这个算法的基本思路是:有一系列称为“GC ROOTS”的对象作为起始点,从这个起始点开始寻找,能到达的对象就不能被回收,不能到达的对象就需要被回收。GC ROOTS就好比一颗大树的树根,往上找树枝,树叶。有一些对象,GC ROOTS找不到和它的联系,那这个对象就需要被回收。

有以下4种对象,作为GC ROOTS使用;

1 .虚拟机栈(栈帧中的本地变量表)所引用的对象

2 .方法区中静态属性所引用的对象

3 .方法区中常量所引用的对象

4 .本地Native方法(本地方法)所引用的对象


3、 内存溢出和泄漏

3.1 内存泄漏

程序中己动态分配的堆内存由于某种原因程序未释放或无法释放

内存泄漏,即部分对象虽然已经不再使用,但是因为有root持有引用,所以并没有被销毁,所占用的内存一直没有被释放。一次两次发生影响不大。如果频繁发生,那么可用内存会渐渐不足,最终在某一次请求内存时发现内存不足而发生oom。这里要明确一个概念,只有强引用会发生内存泄漏,而weak等引用因为其特殊机制,所以影响不大。

GC roots直接或者间接引用的对象,不可回收,造成泄漏

最简单的方法自然就是使用leakcanary了。只要给自己的项目加上这个工具,在发生泄漏的时候很快就会有提示。

3.2 内存溢出

通俗理解就是内存不够

常见的有以下几种: 1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据; 2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收; 3.代码中存在死循环或循环产生过多重复的对象实体;


4、内存泄漏检测工具LeakCanary

LeakCanary是Square公司为Android开发者提供的一个自动检测内存泄漏的工具,

LeakCanary本质上是一个基于MAT进行Android应用程序内存泄漏自动化检测的的开源工具,我们可以通过集成LeakCanary提供的jar包到自己的工程中,一旦检测到内存泄漏,LeakCanary就好dump Memory信息,并通过另一个进程分析内存泄漏的信息并展示出来,随时发现和定位内存泄漏问题,而不用每次在开发流程中都抽出专人来进行内存泄漏问题检测,极大地方便了Android应用程序的开发。

使用

需要使用的地方添加依赖:implementation'com.squareup.leakcanary:leakcanary-android:1.6.1'

在我们自定义Application的onCreate方法中注册LeakCanary;也可以监听指定对象,在Application的onCreate中调用install方法,并获取RefWatcher对象:

注册LeakCanary 监听activity

5、AndroidStudio中性能工具Profiler

操作 内存检测 具体情况

6、内存优化

内存主要有三个方面的问题:内存泄漏,内存抖动,内存碎片

4中工具检测内存泄漏

4中工具可以检测内存抖动,碎片等问题

内存泄漏解决方案:弱引用

内存抖动:减少方法内引用变量的重复创建

内存碎片:重复类型变量使用变量池Pools.Pool(实现:SimplePool,线程安全SynchronizedPool)

具体接口
上一篇 下一篇

猜你喜欢

热点阅读