一篇文章教你搞定内存泄漏与排查流程——安卓性能优化

本文详细介绍了JAVA内存解析、回收机制、四种引用,重点讲解了Android内存泄漏的排查工具,如Android Profiler和MAT,以及内存泄漏的检查与解决流程。通过实例分析了常见的内存泄漏原因,如集合类、单例模式、未关闭资源、Handler和Thread等,旨在帮助开发者提升安卓应用的性能优化能力。
摘要由CSDN通过智能技术生成

前言

内存泄漏可以说是安卓开发中常遇到的问题,追溯和排查其问题根源是进阶的程序猿必须具备的一项技能。小盆友今天便与大家分享一下这方面的一些见解,如有理解错误或是不同见解,可以于评论区留言我们进行讨论,如果喜欢给个赞鼓励下吧。

目录

1、JAVA内存解析
2、JAVA回收机制
3、四种引用
4、小结
5、安卓内存泄漏排查工具
6、内存泄漏检查与解决流程
7、常见的内存泄漏原因

1、JAVA内存解析

要想知道内存泄漏,需要先了解java中运行时内存是怎么构成的,才能知道是哪个地方导致。话不多说,先上图

运行时的java内存分为两大块:线程私有(蓝色区域)、共享数据区(黄色区域)
线程私有:主要用于存储各个线程私有的一些信息,包括:程序计数器、虚拟机栈、本地方法栈
共享数据区:主要用于存储公用的一些信息,包括:方法区(内含常量池)、堆

  1. 程序计数器:让程序中各个线程知道自己接下来需要执行哪一行。在java中多线程为抢占式(因为cpu在某一时刻只会执行一条线程),当线程切换时,需要继续哪一行便由程序计数器告知。

    举个例子:A、B两条线程,此时CPU执行从A切换至B,过了段时间从B切换回A,此时A需要从上次暂停的地方继续执行,此时从哪一行执行就是由程序计数器来提供。

    值得一提
    (1)若执行java函数时,程序计数器记录的是虚拟机字节码的地址;
    (2)若执行native方法时,程序计数器便置为了null。
    (3)在java虚拟机规范中,程序计数器是唯一没有定义OutOfMemoryError。

  2. 虚拟机栈:描述的是java方法的内存模型,平时说的“栈”其实就是虚拟机栈,其生命周期与线程相同。每个方法(不包含native方法)执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。

    值得一提:在java虚拟机规范中,此处定义了两个异常
    (1)StackOverFlowError (在递归中常看到,递归层级过深)
    (2)OutOfMemoryError

  3. 本地方法栈:是为虚拟机使用到的Native方法提供内存空间。 有些虚拟机的实现直接把本地方法栈和虚拟机栈合二为一,比如主流的HotSpot虚拟机。

    值得一提:在java虚拟机规范中,此处定义了两个异常
    (1)StackOverFlowError (在递归中常看到,递归层级过深)
    (2)OutOfMemoryError

  4. 方法区:主要存储已加载是类信息(由ClassLoader加载)、常量、静态变量、编译后的代码的一些信息。 GC在这里比较少出现在这块区域。

  5. 堆:存放的是几乎所有的对象实例和数组数据。 是虚拟机管理的最大的一块内存,是GC的主战场,所以也叫“GC堆”、“垃圾堆” 。

    值得一提:在java虚拟机规范中,此处定义了一个异常
    (1)OutOfMemoryError

  6. 运行时常量池:属于“方法区”的一部分,用于存放编译器生成的各种字面量和符号引用。
    字面量:与Java语言层面的常量概念相近,包含文本字符串、声明为final的常量值等。
    符号引用:编译语言层面的概念,包括以下3类:
    (1) 类和接口的全限定名
    (2)字段的名称和描述符
    (3)方法的名称和描述符

2、JAVA回收机制

java中是通过GC(Garbage Collection)来进行回收内存,那jvm是如何确定一个对象能否被回收的呢?这里就需讲到其回收使用的算法

(1) 引用计数算法

引用计数是垃圾收集器中的早期策略。在这种方法中,堆中每个对象实例都有一个引用计数。当一个对象被创建时,且将该对象实例分配给一个变量,该变量计数设置为1。当任何其它变量被赋值为这个对象的引用时,计数加1(a = b,则b引用的对象实例的计数器+1),当一个对象实例的某个引用超过了生命周期或者被设置为一个新值时,对象实例的引用计数器减1。任何引用计数器为0的对象实例可以被当作垃圾收集。当一个对象实例被垃圾收集时,它引用的任何对象实例的引用计数器减1。

优点:
  引用计数收集器可以很快的执行,交织在程序运行中。对程序需要不被长时间打断的实时环境比较有利。

缺点:
  无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为0。例如下面代码片段中,最后的Object实例已经不在我们的代码可控

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值