谁不是一边燃一边丧,一边拼命一边又不想活了。
最近这阵子又回来爱奇艺实习了,实习的任务是分析爱奇艺的APM平台上的卡顿栈的问题。爱奇艺的APM平台上的卡顿栈都是系统栈,很少有比较明显的栈。因此,只能从源码开始逐层分析。通过分析源码的逐层调用,来判断是否是因为主线程(UI线程)持有子线程的锁导致卡顿,亦或者是由于频繁的进行IPC导致,或者是因为读写竞争导致的问题……
对于源码的分析有利于快速的定位到问题所在,当然,可以借此机会,深入了解Android底层原理和实现。工作本身就是枯燥无味的,但是能够将枯燥无味的生活变为提升自己的方式,有何不可呢?
看源码还是看这个好:BeesAndroid——This project aims to help more wireless development engineers understand and master the Android system by providing a series of tools and methods.
这里的教程也是基于这个项目而写的,欢迎关注这个项目。
在线撸源码的网站:http://androidxref.com/
repo是拉取谷歌官方源码的工具,必须要用到它。
下载repo,默认是官方源:
mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
如果你没有,可以使用清华大学的repo镜像:https://mirrors.tuna.tsinghua.edu.cn/help/git-repo/
下载完成后将bin/repo打开,将里面的REPO_URL改成清华大学的镜像:
https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'
git config --global user.text "Your Name"
git config --global user.email "[email protected]"
如果是没在的环境中,就需要配置下git的代理:
git config --global http.proxy 'socks5://127.0.0.1:1080'
git config --global https.proxy 'socks5://127.0.0.1:1080'
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest
如果需要某个特定的Android版本,可以在后面指定版本号。
Android系统各版本号:https://source.android.com/source/build-numbers.html#source-code-tags-and-builds
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-7.1.1_r28
注:更多源码版本可以参见https://source.android.com/source/build-numbers
注意:源码编译之后大概有140G的大小,请确保有充足的空间来下载源码并编译。如果是希望导入到IDEA中,需要对源码进行编译,我编译Android 7.1.1大概花了两个小时多。
同步源码树,开始下载源码,如果后续下载中断,也可以重复执行这个命令。
# 单线程
repo sync
# 指定并发数
repo sync -j4
源码的下载会经常中断,我们可以写一个脚本自动repo sync,保存成repo.sh
,放到WORKING_DIRECTORY目录下
#!/bin/bash
#FileName jkYishon.sh
PATH=~/bin:$PATH
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-7.1.1_r28
repo sync
while [ $? = 1 ]; do
echo "================sync failed, re-sync again ====="
sleep 3
repo sync
done
配置可执行权限,运行即可。
chmod 777 repo.sh
./repo.sh
Android 7.1.1的源码依赖的是OpenJDK 8版本,因此需要安装下:
sudo apt-get update
sudo apt-get install openjdk-8-jre
sudo apt-get install openjdk-8-jdk
配置环境:sudo vim /etc/profile
添加以下内容,之后执行source /etc/profile
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
临时方案:在工作的Terminal中输入export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64;export PATH=/usr/lib/jvm/java-1.8.0-openjdk-amd64/bin:$PATH
切换当前的Java版本
sudo update-alternatives --config java
sudo update-alternatives --config javac
这是编译需要的一些环境,需要先安装完毕,sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib flex bison gperf build-essential libncurses5-dev:i386 tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386 dpkg-dev libsdl1.2-dev libesd0-dev gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev libgl1-mesa-dev libxml2-utils xsltproc unzip m4 lib32z-dev ccache
。
顺便安装:sudo apt-get install gcc
之后顺手更新下系统吧:sudo apt-get clean && sudo apt-get update && sudo apt-get upgrade -y && sudo apt-get dist-upgrade -y
。
不修改我会遇到这种问题:build/core/ninja.mk:148: recipe for target 'ninja_wrapper' failed
修改android-7.1/prebuilts/sdk/tools/jack-admin,找到以下内容:
JACK_SERVER_COMMAND="java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -cp $LAUNCHER_JAR $LAUNCHER_NAME"
改为:
JACK_SERVER_COMMAND="java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -Xmx4096M -cp $LAUNCHER_JAR $LAUNCHER_NAME"
建议编译机器的内存大于8G,╮(╯▽╰)╭
Jack服务的基本命令:
./prebuilts/sdk/tools/jack-admin list-server
prebuilts/sdk/tools/jack-admin start-server
prebuilts/sdk/tools/jack-admin stop-server
检查下是否安装了Jack服务:./prebuilts/sdk/tools/jack-admin list-server
如果不存在,就直接安装就好了:
cd prebuilts/sdk/tools/
./jack-admin install-server jack-launcher.jar jack-server-4.8.ALPHA.jar
如果出现了以下问题,就是需要分配更多的内存:
Try increasing heap size with java option '-Xmx' .
Warning: This may have produced partial or corrupted output.
如果是内存足够,可以给Jack分配更多的内存:
# 给6G:-Xmx6g
export ANDROID_JACK_VM_ARGS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx6g"
prebuilts/sdk/tools/jack-admin stop-server
prebuilts/sdk/tools/jack-admin start-server
更多问题请见:ubuntu 18.04编译Android 7.1源码
初始化环境变量:source build/envsetup.sh
选择版本:lunch
选择要编译的版本,可以选aosp_arm-eng的,编译:make -j8
,j8
表示线程数,最好和CPU核数一致。
大概需要编译两个多小时,耐心等候。╮(╯▽╰)╭
编译成功的时候:
初始化环境变量:source build/envsetup.sh
运行命令,生成android.ipr文件:make idegen && development/tools/idegen/idegen.sh
大概需要花10多分钟吧,耐心等候,之后会在工程的根目录下生成android.iml
和android.ipr
两个文件。
接下来我们就要导入源码,但是源码的体积很大,如果全部导入会比较卡,我们可以排除一些代码。例如我只想研究framework
里的代码,我们可以在android.iml
了添加以下内容。
<excludeFolder url="file://$MODULE_DIR$/.repo" />
<excludeFolder url="file://$MODULE_DIR$/abi" />
<excludeFolder url="file://$MODULE_DIR$/art" />
<excludeFolder url="file://$MODULE_DIR$/bionic" />
<excludeFolder url="file://$MODULE_DIR$/bootable" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/cts" />
<excludeFolder url="file://$MODULE_DIR$/dalvik" />
<excludeFolder url="file://$MODULE_DIR$/developers" />
<excludeFolder url="file://$MODULE_DIR$/development" />
<excludeFolder url="file://$MODULE_DIR$/device" />
<excludeFolder url="file://$MODULE_DIR$/docs" />
<excludeFolder url="file://$MODULE_DIR$/external" />
<excludeFolder url="file://$MODULE_DIR$/hardware" />
<excludeFolder url="file://$MODULE_DIR$/libcore" />
<excludeFolder url="file://$MODULE_DIR$/libnativehelper" />
<excludeFolder url="file://$MODULE_DIR$/ndk" />
<excludeFolder url="file://$MODULE_DIR$/out" />
<excludeFolder url="file://$MODULE_DIR$/packages" />
<excludeFolder url="file://$MODULE_DIR$/pdk" />
<excludeFolder url="file://$MODULE_DIR$/prebuilt" />
<excludeFolder url="file://$MODULE_DIR$/prebuilts" />
<excludeFolder url="file://$MODULE_DIR$/sdk" />
<excludeFolder url="file://$MODULE_DIR$/system" />
<excludeFolder url="file://$MODULE_DIR$/tools" />
添加完毕,我们大概IDEA或者AS,打开android.ipr
文件,就会将整个工程导入,可能会需要花十几分钟。
export ANDROID_PRODUCT_OUT=out/target/product/generic
export ANDROID_BIN=out/host/linux-x86/bin
PATH=$ANDROID_BIN:$PATH
source build/envsetup.sh
lunch aosp_arm-eng
emulator64-arm -gpu off -memory 2048