分析卡顿发生在什么函数,资源占用情况的方法
-
利用UI线程的Looper打印的日志匹配
Looper比较适合在发布前进行测试或者小范围灰度测试然后定位问题
-
使用Choreographer.FrameCallback
是否监控线上环境的App的掉帧情况来计算app在某些场景的流畅度然后针对性的做性能优化.
Android 系统为每个应用分配的内存规则
- app启动分配的初始化内存大小是16M
- 系统分配单个app堆内存的最大显示为192M,超过就会OOM内存溢出
- 如果在清单文件中Application添加largeHeap属性后,耽搁APp堆内存的最大值为512M
产生OOM的原因
- java堆内存溢出
- 无足够连续内存空间
- FD(文件句柄)数量超出限制
- 线程数量超出限制
- 虚拟内存不足
activity启动流程
- 点击桌面应用图标,Launcher进程将启动Activity(MainActivity)的请求以Binder的方式发送给了AMS。
- AMS接收到启动请求后,交付ActivityStarter处理Intent和Flag等信息,然后再交给ActivityStackSupervisior/ActivityStack
处理Activity进栈相关流程。同时以Socket方式请求Zygote进程fork新进程。 - Zygote接收到新进程创建请求后fork出新进程。
- 在新进程里创建ActivityThread对象,新创建的进程就是应用的主线程,在主线程里开启Looper消息循环,开始处理创建Activity。
- ActivityThread利用ClassLoader去加载Activity、创建Activity实例,并回调Activity的onCreate()方法。这样便完成了Activity的启动。
有现有的IPC方式,为什么重新设计一套Binder机制呢?
主要是出于以上三个方面的考量:
-
高性能:
从数据拷贝次数来看Binder只需要进行一次内存拷贝,而管道、消息队列、Socket都需要两次,共享内存不需要拷贝,Binder的性能仅次于共享内存。
-
稳定性:
上面说到共享内存的性能优于Binder,那为什么不适用共享内存呢,因为共享内存需要处理并发同步问题,控制负责,容易出现死锁和资源竞争,稳定性较差。而Binder基于C/S架构,客户端与服务端彼此独立,稳定性较好。
-
安全性:
我们知道Android为每个应用分配了UID,用来作为鉴别进程的重要标志,Android内部也依赖这个UID进行权限管理,包括6.0以前的固定权限和6.0以后的动态权限,传统IPC只能由用户在数据包里填入UID/PID,这个标记完全
是在用户空间控制的,没有放在内核空间,因此有被恶意篡改的可能,因此Binder的安全性更高。
PathClassLoader与DexClassLoader有什么区别
- PathClassLoader:只能加载已经安装到Android系统的APK文件,即/data/app目录,Android默认的类加载器。
- DexClassLoader:可以加载任意目录下的dex、jar、apk、zip文件。