Android优化一:提纲
Android优化二:性能检测
Android优化三:内存优化
Android优化四:App启动速度优化
Android优化五:布局优化
Android优化六:性能优化
前言
最近在找工作,面了很多家公司,面试官对于Handler消息机制和Android性能优化、OOM异常这几个问题几乎是必问,烦不胜烦。
以前写了一盘很长很长的文章,后面发现太长了,自己都看不下去,现在按功能拆分成几部分。
Java的GC机制
- 引用计数法(Java中基本不用,Python用)
- 可达性分析法(现在Java用这个)
垃圾回收算法
- 标记-清除
- 复制
- 标记-整理
- 分代收集算法(新生代和老生代)
结合使用,新生代的GC比较频繁,使用复制的方法效率高,在新生代存活很久后,进入老生代,老生代GC少,使用标记-整理的方法。
Java类加载机制
- 双亲机制
当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。
- 为什么要使用双亲机制?
因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。
考虑到安全因素,我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义的类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时就被引导类加载器(Bootstrcp ClassLoader)加载,所以用户自定义的ClassLoader永远也无法加载一个自己写的String,除非你改变JDK中ClassLoader搜索类的默认算法。
- JVM在搜索类的时候,又是如何判定两个class是相同的呢?
类名想同 + 使用同一个类加载器
Android类加载机制
对于Android而言,最终的apk文件包含的是dex类型的文件,dex文件是将class文件重新打包,打包的规则又不是简单地压缩,而是完全对class文件内部的各种函数表,变量表进行优化,产生一个新的文件,即dex文件。因此加载这种特殊的Class文件就需要特殊的类加载器DexClassLoader。
内存区分
- 寄存器Registers:用于存储指令、地址、数据。
- 栈Stack:基本数据类型、对象的引用、函数地址,由系统控制。
- 堆Heap:存放对象本身和数组,由开发者控制。
- 静态域static field:存储静态变量。
- 常量池constant pool:存放常量。
堆是被所有的内存所共享的,但是每一个线程对应一个私有的栈。Java中所有的变量都存在主内存中,线程的工作内存保存了该线程所使用的变量,这些变量都是从主内存中拷贝出来的,线程对变量的所有操作(读取,赋值)都必须在工作内存中进行。不同线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。
这也是多线程并发的三大特性“有序性”的产生原因。
Java中的“引用”
- 强引用:GC永远都不会被回收
- 软引用:在内存溢出的时候,被GC回收掉。
- 弱引用:当GC执行后,对象都会被回收掉。
- 虚引用:在GC回收时收到一条通知。
开发者能控制的内存基本在于堆和栈。
Q:你是如何处理内存泄漏的?
①在开发过程中避免写出有内存泄漏的代码
②通过一些分析工具比如MAT来找出潜在的内存泄露,然后解决。
鸣谢
《Android群英传》
《Android群英传之神兵利器》
《Android 开发艺术探索》
与性能优化相关面试题六
Android性能优化-内存泄漏(上)
给 App 提速:Android 性能优化总结
Android应用开发性能优化完全分析
《Android 开发艺术探索》 15-Android性能优化
Android内存泄漏总结