动脑学院高级Android知识笔记
第一章 高手筑基基础技能
1.1Java虚拟机
1.JVM内存模型
JVM共可划分为五大内存区域,如下所示
- 虚拟机栈
- 本地方法栈
- 程序计数器
- 堆
- 方法区
其中,虚拟机栈,本地方法栈,程序计数器是线程私有的,堆和方法区是线程共享的
栈帧的组成
- 局部变量表
- 操作数栈
- 动态链接
- 方法出口
堆内存的划分
年轻代和老年代,一般老年代占比80% 年轻代占比20%
年轻代划分为:
- Eden区
- Survivor区
- from
- to
GC算法:
Minor GC(Young GC):新生代GC,即目标只是新生代的垃圾收集
Major GC(Old GC):老年代GC,即目标只是老年代的垃圾收集
Full GC:整堆收集,收集整个Java堆和方法区的垃圾收集
参考文章:https://blog.csdn.net/Alpha_Paser/article/details/82533128
面试题:一个大对象分配内存会直接进入老年代吗?
答案:会,大对象直接进入老年代,避免在新生代的Eden和Survivor区来回复制,产生大量内存复制操作
知识点:在JVM五大内存区域中,只有程序计数器是没有内存溢出的
2.垃圾回收算法
垃圾分析算法
- 引用计数算法
- 可达性分析算法
引用计数算法:每当一个对象被引用一次的时候,引用计数就加1,这种算法存在缺陷,如循环引用,即两个对象互相引用,引用计数都为1,导致无法被回收,故主流的Java虚拟机都没有采用引用计数算法
垃圾回收算法
- 标记清除算法
- 复制算法
- 标记整理算法
- 分代回收算法
标记清除算法:最基础的算法,标记要清理的对象,标记完成后,统一清理,效率虽然高,但是会存在内存碎片
标记复制算法:划分两块区域,垃圾回收时,将存活的对象复制到另一快区域,避免内存碎片,新生代内存回收就是采用这种算法,划分为Eden区和Survivor区,Survivor分为from和to两个区域,每次垃圾回收时,将Eden和from中存活的对象复制到to中
3.强引用,弱引用,软引用,虚引用
强引用:GC不会去回收强引用,宁愿抛出OOM
弱引用: 在系统内存不足时,GC才会考虑回收弱引用
软引用:软引用的对象只能生存到下一次GC之前,当垃圾收集器工作时,会回收软引用关联的对象
虚引用:随时可能被回收
4.两次标记和finalize
当一个对象在可达性分析算法中判定不可达后,并不会立即被垃圾回收器回收,而是会被标记一次,然后会调用finalize方法,可以在这个方法中自救,重新可达,即可避免被回收,接下来会进行第二次标记,后续就会被回收
第二章 Android面试题
2.1Handler消息机制
1.主线程Looper和MessageQueue的创建流程?
一切的一切得从activityThread说起,它是我们的主线程,或者说UI线程,但是它并不是一个thread类,activityThread与一个main方法,从这里开始启动我们的线程
1 | public static void main(String[] args) { |
Looper的创建流程图:
1 | Looper.prepareMainLooper(); -> prepare() -> new Looper() -> 将Looper对象放进threadLocal中 |
MessageQueue的创建(在new Looper的构造方法中):
1 | mQueue = new MessageQueue(quitAllowed); |
有此我与你分享完Looper和MessageQueue的创建
Looper的loop循环
在上一小节中我们看到了Looper创建完成后,调用了Looper.loop()方法,由此开启了loop循环,核心代码:
1 | for (;;) { |
解析:在loop循环中,会获取一条消息,然后调用target.dispatchMessage,这里的target就是handler
1 | public void dispatchMessage(@NonNull Message msg) { |
当我们创建handler,并重写了handleMessage,这里就会最终执行我们的代码
2.ThreadLocal是什么,以及在它消息机制中的作用?
含义:ThreadLocal是一个线程的存储类,提供了get和set方法,它是与线程绑定在一起的,在消息机制中的作用就是,用于存储当前线程的Looper对象,内部使用的ThreadLocalMap来存储,key为当前线程,value为looper对象
Looper的prepare方法:
1 | private static void prepare(boolean quitAllowed) { |
Looper的myLooper方法:
1 | public static @Nullable Looper myLooper() { |