IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Android如何查找java代码编译路径 -> 正文阅读

[Java知识库]Android如何查找java代码编译路径

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. 看一下实际效果

  1. 加入日志,如在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”);
    //…
    }
    }

  2. 找到手机的文件
    /apex # find . -name “core-libart*”
    ./com.android.art/javalib/core-libart.jar
    ./com.android.art@319999900/javalib/core-libart.jar

  3. pull出来adb pull /apex/com.android.art/javalib/core-libart.jar core-libart_new.jar

  4. 转换成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"          //常量v0是"FinalizerDaemon doFinalize yunhen" 

    invoke-static {v0}, Ljava/lang/System;->logE(Ljava/lang/String;)V //调用logE打印日志

    .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");
            //System.logE("FinalizerDaemon yunhen"); //build error
        }
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-04 15:22:29  更:2022-03-04 15:22:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:46:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码