2024年最全Android性能之内存泄漏(1),2024年最新面试题分享一个有趣的经历

如何成为Android高级架构师!

架构师必须具备抽象思维和分析的能力,这是你进行系统分析和系统分解的基本素质。只有具备这样的能力,架构师才能看清系统的整体,掌控全局,这也是架构师大局观的形成基础。 你如何具备这种能力呢?一是来自于经验,二是来自于学习。

架构师不仅要具备在问题领域上的经验,也需要具备在软件工程领域内的经验。也就是说,架构师必须能够准确得理解需求,然后用软件工程的思想,把需求转化和分解成可用计算机语言实现的程度。经验的积累是需要一个时间过程的,这个过程谁也帮不了你,是需要你去经历的。

但是,如果你有意识地去培养,不断吸取前人的经验的话,还是可以缩短这个周期的。这也是我整理架构师进阶此系列的始动力之一。


成为Android架构师必备知识技能

对应导图的学习笔记(由阿里P8大牛手写,我负责整理成PDF笔记)

部分内容展示

《设计思想解读开源框架》

  • 目录
  • 热修复设计
  • 插件化框架设计

    《360°全方面性能优化》
  • 设计思想与代码质量优化
  • 程序性能优化

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 使用匿名内部类

  • 使用异步事件处理机制Handler

  • 使用静态变量

  • 资源未关闭

  • 设置监听

  • 使用AsyncTask

  • 使用Bitmap

上面就是我列出的几个常出现内存泄漏的几个点,下面我们将一一解读。

三、java虚拟机内存管理


java虚拟机内存分为虚拟机栈,本地方法栈,程序计数器,堆,方法区这几个模块,下面我们就来分析下各个模块。

(1).虚拟机栈

虚拟机栈主要的作用就是为执行java方法服务的,是Java方法执行的动态内存模型。会导致栈内存溢出(StackOverFlowError)

(2).本地方法栈

为执行native方法服务的,其他和虚拟机栈一样

(3).程序计数器

是当前线程执行的字节码行号指示器

处于线程独占区

如果是执行的是java代码,当前值为字节码指令的地址,如果是Native,值为undefined

(4).堆

存放对象的实例

垃圾收集器管理的主要区域

分代管理对象

会导致内存溢出(OutOfMemoryError)

(5).方法区

存放虚拟机加载的类信息,常量,静态变量,编译后的代码和数据

GC主要对方法区进行常量回收和类卸载

会出现内存溢出(OutOfMemoryError)

四、java内存几种分配策略?


可以结合上面的内存分配模型,能很好的理解。

(1).静态的

静态存储区:内存在程序编译期间就已经分配完成,一般来说,这个区域在程序运行期间一直处在

它主要储存静态数据,全局静态数据和常量

(2).栈式的

执行方法时,存储局部变量(编译期间,已经确定占用内存大小),操作数,动态链接,方法出口

(3).堆式的

也叫动态内存分配,主要存储对象实例,以及已经被加载类的Class对象(用于反射)

五、垃圾收集器是如何判断对象是否可回收?


我们知道内存泄漏的原因是应该被回收的对象,不能被及时回收,那么GC是如何来判断对象是否为垃圾对象呢?

判断的方式有两个:

  • 引用计数

    对象被引用,引用计数器加1,反之减一,只有引用计数为0,那么这个对象为垃圾对象

  • 可达性

    从GCRoot节点对象开始,看是否可以访问到此对象,如果没有访问到则为垃圾对象

可以作为GCRoot对象有以下几种:

虚拟机栈中的局部变量

本地方法栈中的引用对象

方法区中的常量引用对象

方法区中的类属性引用对象

在native层和早期的虚拟机一般使用引用计数,但是现在的java虚拟机大多使用的是可达性。

六、什么是内存抖动?


堆内存都有一定的大小,能容纳的数据是有限制的,当Java堆的大小太大时,垃圾收集会启动停止堆中不再应用的对象,来释放内存。当在极短时间内分配给对象和回收对象的过程就是内存抖动。

七、内存抖动产生的原因?


从术语上来讲就是极短时间内分配给对象和回收对象的过程。

一般多是在循环语句中创建临时对象,在绘制时配置大量对象或者执行动画时创建大量临时对象

内存抖动会带来UI的卡顿,因为大量的对象创建,会很快消耗剩余内存,导致GC回收,GC会占用大量的帧绘制时间,从而导致UI卡顿,关于UI卡顿会在后面章节讲到。

八、android中4种引用


(1).StrongReference强引用

从不被回收,java虚拟机停止时,才终止

(2).SoftReference软引用

当内存不足时,会主动回收,使用SoftReference使用结合ReferenceQueue构造有效期短

(3).WeakReference弱引用

每次垃圾回收时,被回收

(4).PhatomReference虚引用

每次垃圾回收时,被回收.结合ReferenceQueue来跟踪对象被垃圾回收器回收的活动

九、常见的导致内存泄漏的示例


(1).使用单例模式


    private static ComonUtil mInstance = null;

    private Context mContext = null;



    public ComonUtil(Context context) {

        mContext = context;

    }



    public static ComonUtil getInstance(Context context) {

        if (mInstance == null) {

            mInstance = new ComonUtil(context);

        }

        return mInstance;

    }



使用:

ComonUtil mComonUtil = ComonUtil.getInstance(this);

我们看到上面的代码就是我们平时使用的单例模式,当然这里没有考虑线程安全,请忽略。当我们传递进来的是Context,那么当前对象就会持有第一次实例化的Context,如果Context是Activity对象,那么就会产生内存泄漏。因为当前对象ComonUtil是静态的,生命周期和应用是一样的,只有应用退出才会释放,导致Activity不能及时释放,带来内存泄漏。

怎么解决呢?

常见的有两种方式,第一就是传入ApplicationContext,第二CommonUtil中取context.getApplicationContext()。


    public ComonUtil(Context context) {

        mContext = context.getApplicationContext();

    }



(2).使用非静态内部类


    /**

     * 非静态内部类

     */

    public void createNonStaticInnerClass(){

        CustomThread mCustomThread = new CustomThread();

        mCustomThread.start();

    }



    public class CustomThread extends Thread{

        @Override

        public void run() {

            super.run();

            while (true){

                try {

                    Thread.sleep(5000);

                    Log.i(TAG,"CustomThread ------- 打印");

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }

    }



我们就以线程为例,当Activity调用了createNonStaticInnerClass方法,然后退出当前Activity时,因为线程还在后台执行且当前线程持有Activity引用,只有等到线程执行完毕,Activitiy才能得到释放,导致内存泄漏。

常用的解决方法有很多,第一把线程类声明为静态的类,如果要用到Activity对象,那么就作为参数传入且为WeakReference,第二在Activity的onDestroy时,停止线程的执行。


public static class CustomThread extends Thread{

    private WeakReference<MainActivity> mActivity;

    public CustomThread(MainActivity activity){

        mActivity = new WeakReference<MainActivity>(activity)

    }

}



最后

在此为大家准备了四节优质的Android高级进阶视频:

架构师项目实战——全球首批Android开发者对Android架构的见解

附相关架构及资料

image.png

往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

roid开发者对Android架构的见解**

附相关架构及资料

[外链图片转存中…(img-GxcXSBLy-1715119356465)]

往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 14
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值