1. 源文件代码位置
如果有code search,那么直接使用code search, 如果没有可以使用locate "***.java"来查找对应的文件
举一个例子想要调试FinalizerDaemon这个class,先“frameworks/base”搜索一下 在frameworks/base/config/preloaded-classes可以找到类似定义
java.lang.Daemons$FinalizerDaemon
那么我们其实应该去找Daemons.java在哪里 locate “Daemons.java” 可以找到源码位置
libcore/libart/src/main/java/java/lang/Daemons.java
不过直接修改这个文件发现修改不生效,那么很大可能就是没有编译进去,接下去需要看一下这个文件编译在哪里
2. 查找文件编译后存放的地方
1、libcore/libart/src/main/java/java/lang/Daemons.java 逐级往上查找Android.mk、Android.bp
如这里最近的就是libcore\Android.bp
2、在Android.bp的目录libcore, 先搜索一下Daemons.java或者libcore find -name “*.bp” |xargs grep “Daemons”
./non_openjdk_java_files.bp: “libart/src/main/java/java/lang/Daemons.java”,
libcore$ find -name “*.bp” |xargs grep “libart”
./non_openjdk_java_files.bp: path: “libart/src/main”,
上面2中都是可以将Daemons.java引用进来
3、打开搜索到的文件libcore/non_openjdk_java_files.bp
//文件组 filegroup { //名字 name: “non_openjdk_javadoc_libart_files”, //源文件,如frameworks/base/core/java/Android.bp中的"**/*.java"代表将frameworks/base/core/java后面的所有java文件做为资源,包括Activity.java srcs: [ //… “libart/src/main/java/java/lang/Daemons.java”, //… ], //路径,从这里开始引入源码 path: “libart/src/main”, //私有的,这个文件组只有libcore本包可以访问,其它子包Android.bp访问不了 visibility: ["//visibility:private"], }
4、non_openjdk_javadoc_libart_files使用的地方是non_openjdk_javadoc_files,还是文件组,不是生成文件的地方
filegroup { name: “non_openjdk_javadoc_files”, srcs: [ //… “:non_openjdk_javadoc_libart_files”, //… ], visibility: ["//visibility:private"], }
5、接着继续找non_openjdk_javadoc_files使用的地方,是core_libart_api_files/non_openjdk_java_files文件组 libcore$ find -name “*.bp” |xargs grep “non_openjdk_javadoc_files” ./JavaLibrary.bp: “:non_openjdk_javadoc_files”, ./non_openjdk_java_files.bp: name: “non_openjdk_javadoc_files”, ./non_openjdk_java_files.bp: “:non_openjdk_javadoc_files”,
//JavaLibrary.bp filegroup { name: “core_libart_api_files”, srcs: [ “:non_openjdk_javadoc_files”, ], }
//non_openjdk_java_files.bp filegroup { name: “non_openjdk_java_files”, visibility: [ “//frameworks/base”, ], srcs: [ //… “:non_openjdk_javadoc_files”, ], }
6、core_libart_api_files看起来都是用在接口的地方,没有包含实际运行的逻辑
//被java_sdk_library引用,一般是用于接口 java_sdk_library { name: “art.module.public.api”, //… srcs: [ //… “:core_libart_api_files”, //… ], //… }
//引用在droidstubs,用于生成接口 droidstubs { name: “java-current-stubs-source”, //… srcs: [ //… “:core_libart_api_files”, //… ], //… }
//art_module_api_files是filegroup文件组,还是要继续找 filegroup { name: “art_module_api_files”, //… srcs: [ //… “:core_libart_api_files”, //… ], //… }
//art_module_api_files引用在droidstubs,用于生成接口 droidstubs { name: “art-module-public-api-stubs-nullability-validation”, srcs: [":art_module_api_files"], //… }
7、non_openjdk_java_files被core_libart_java_files引用,也是文件组 filegroup { name: “core_libart_java_files”, //可以被子包应用,如果libcore子目录有Android.bp子包,也是可以用这个filegroup的 visibility: [ “//libcore:subpackages”, ], srcs: [ “:non_openjdk_java_files”, ], }
8、core_libart_java_files被core-libart引用,这个是一个java_library(java的库,如.jar)是可以生成文件的看起来像是了 java_library { name: “core-libart”, visibility: [ “//art/build/apex”, “//art/build/sdk”, “//external/wycheproof”, “//libcore/benchmarks”, “//packages/modules/ArtPrebuilt”, ], //… srcs: [":core_libart_java_files"], //… }
3. 找一下这个文件在哪里
1、可以搜索生成文件 $ locate “core-libart.jar” ArtPrebuilt/com.google.android.art.deapexer/android_common/deapexer/javalib/core-libart.jar dex_artjars_input/core-libart.jar
到这里可以看到这个是在art
那么大概原因应该已经知道了,应该是mainline导致了代码没有生效
手机apex里面也可以找到这个jar包 apex # find . -name “core-libart” ./com.android.art/javalib/core-libart.jar ./com.android.art@310924000/javalib/core-libart.jar
2、接着去源码art目录看一下是如何使用这个jar的 //art/build/apex/Android.bp
//放在libcore_java_libs列表里面 // Core Java libraries. libcore_java_libs = [ “core-oj”, “core-libart”, “okhttp”, “bouncycastle”, “apache-xml”, ]
//host主机端,也不是终端里面,不是这个 art_apex_test_host { name: “com.android.art.host”, //… java_libs: libcore_java_libs, //… ]
//这个是defaults,还有别的地方引用 apex_defaults { name: “com.android.art-device-defaults”, defaults: [“com.android.art-defaults”], //… java_libs: libcore_java_libs, //… ]
//这个就是给mainline了的 art_apex { name: “com.android.art”, defaults: [“com.android.art-device-defaults”], certificate: “:com.android.art.certificate”, }
3、那么去掉mainline重新编译应该是生效的
diff --git a/build/mainline_modules_s.mk b/build/mainline_modules_s.mk
--- a/build/mainline_modules_s.mk
+++ b/build/mainline_modules_s.mk
+# delete by yunhen
# Art
-MAINLINE_COMPRESS_APEX_ART ?= true
-ifeq ($(MAINLINE_COMPRESS_APEX_ART),true)
-PRODUCT_PACKAGES += \
- com.google.android.art_compressed
-else
-PRODUCT_PACKAGES += \
- com.google.android.art
-endif
+#MAINLINE_COMPRESS_APEX_ART ?= true
+#ifeq ($(MAINLINE_COMPRESS_APEX_ART),true)
+#PRODUCT_PACKAGES += \
+# com.google.android.art_compressed
+#else
+#PRODUCT_PACKAGES += \
+# com.google.android.art
+#endif
4. 看一下实际效果
-
加入日志,如在FinalizerDaemon的doFinalize加入一个日志"FinalizerDaemon doFinalize yunhen" //libcore/libart/src/main/java/java/lang/Daemons.java private static class FinalizerDaemon extends Daemon { //… private void doFinalize(FinalizerReference<?> reference) { System.logE(“FinalizerDaemon doFinalize yunhen”); //… } } -
找到手机的文件 /apex # find . -name “core-libart*” ./com.android.art/javalib/core-libart.jar ./com.android.art@319999900/javalib/core-libart.jar -
pull出来adb pull /apex/com.android.art/javalib/core-libart.jar core-libart_new.jar -
转换成smali文件 java -jar apktool_2.3.0.jar d core-libart_new.jar
5.搜索FinalizerDaemon找到Daemons$FinalizerDaemon.smali $ find . -name “FinalizerDaemon” ./smali/java/lang/Daemons$FinalizerDaemon.smali
6.打开Daemons$FinalizerDaemon.smali,果然发现doFinalize有我们加入的代码
.method private doFinalize(Ljava/lang/ref/FinalizerReference;)V
.locals 4
.annotation system Ldalvik/annotation/Signature;
value = {
"(",
"Ljava/lang/ref/FinalizerReference<",
"*>;)V"
}
.end annotation
.line 294
.local p1, "reference":Ljava/lang/ref/FinalizerReference;, "Ljava/lang/ref/FinalizerReference<*>;"
const-string v0, "FinalizerDaemon doFinalize yunhen"
invoke-static {v0}, Ljava/lang/System;->logE(Ljava/lang/String;)V
.line 295
invoke-static {p1}, Ljava/lang/ref/FinalizerReference;->remove(Ljava/lang/ref/FinalizerReference;)V
7、实际手机也会输出 $ adb logcat | grep “FinalizerDaemon doFinalize yunhen” 03-03 15:29:52.648 9462 9478 E System : FinalizerDaemon doFinalize yunhen 03-03 15:30:05.826 2832 2850 E System : FinalizerDaemon doFinalize yunhen 03-03 15:30:05.826 2832 2850 E System : FinalizerDaemon doFinalize yunhen
ps: System.logE 日志打印需要runtime的一些环境,故先不要在FinalizerDaemon的clinit中打印(clinit是类初始化的时候调用,Android的preloaded-classes就是调用clinit,将部分class提前载入zygote),这个函数用在FinalizerDaemon有点特殊,别的如framework的java日志打印调用Log.w或者Slog.w都是没有问题的
dex2oatd F 03-03 11:48:21 4711 4711 unstarted_runtime.cc:2130] Calling native method java.lang.String dalvik.system.VMRuntime.bootClassPath() in an unstarted non-transactional runtime
at dalvik.system.VMRuntime.bootClassPath(Native method)
at java.lang.System.initUnchangeableSystemProperties(System.java:971)
at java.lang.System.<clinit>(System.java:1690)
at java.lang.System.logE(System.java:1727)
at java.lang.Daemons$FinalizerDaemon.<init>(Daemons.java:246)
at java.lang.Daemons$FinalizerDaemon.<clinit>(Daemons.java:237)
at java.lang.Daemons$FinalizerDaemon.access$200(Daemons.java:235)
at java.lang.Daemons.<clinit>(Daemons.java:56)
//如在构造函数FinalizerDaemon中打印日志,本来构造函数不在clinit中,但是静态变量INSTANCE在clinit中,故还是会报错
private static class FinalizerDaemon extends Daemon {
@UnsupportedAppUsage
private static final FinalizerDaemon INSTANCE = new FinalizerDaemon();
FinalizerDaemon() {
super("FinalizerDaemon");
}
|