修改 Android 源码的核心 java 库以用于应用程序

Ric*_* Hu 0 java android build android-build android-source

我想对 Android 源代码进行一些修改以满足我的要求。这是要求:

我想通过向类中再添加一个公共int字段来索引 Android 应用程序中的所有对象java.lang.Object。因此,所有类都可以继承新添加的字段,因为它们都是Object该类的子类。

到目前为止我所做的是修改文件夹java.lang.Object下的类<Android_source>/libcore/libart/src/main/java/java/lang并重新编译源代码。

我想问一下我做的对不对。我的 Android 应用程序能否识别此更改(例如,String对象是否可以访问新添加的字段)?

编辑

经过大约 3 周的尝试和错误,我终于得到了完整的答案。我想,如果别人想修改的Android源的核心Java库(例如,修改与他人分享这方面的经验Object.javaString.java等)。同样,正如迈克尔所提到的,请注意此类修改可能仅适用于研究或测试目的。

成功修改的关键挑战(这里的“成功”意味着修改后的 Android 源代码可以在模拟器或真实设备上构建和运行而没有任何问题)是核心 java 库中的一些类有它们的 C++ 镜像(位于<Android_source>/art/runtime/mirrors/)。在修改这些 java 类时,您也应该对其 C++ 镜像进行相同的修改。否则,您可能会在构建过程中失败,因为您需要通过大量检查。由于我只向 中添加了一个新字段,因此Object.java我将在下面列出我遇到的一些检查(或要求):

1.对象实例的大小=其C++镜像的大小。例如,如果我将一个long字段添加到 中Object.java,我还应该uint64_t向它的 C++ 镜像添加一个字段以使其大小相等。

2. 尝试使对象实例的大小为 2 的幂(例如,2, 4, 8, 16, ...)。比如原来的大小Object.java是8,所以我加了一个long字段,把大小增加到16。如果我加了一个int字段,大小变成了12,很多检查都会失败。我不知道确切的原因,但我想这与memory 对齐有关

3.尽量将原始类型字段放在非原始类型字段之后,原始类型字段应按大小排序。这意味着您应该将引用类型字段放在前面,然后是 8 字节原始类型字段,然后是 4 字节原始类型字段,然后是 2 字节原始类型字段,然后是 1 字节原始类型- 类型字段。同样,我猜原因是内存对齐

这就是我为满足我的要求所做的一切。如果您对这些检查的目的(尤其是第 2 次和第 3 次)有任何想法,我愿意进行任何讨论

新编辑

更具体地说,我做了以下几件事:

  1. 在中添加一个新字段(例如,public long tag;Object.java

  2. 更改static constexpr uint32_t kObjectHeaderSize = kUseBrooksReadBarrier ? 16 : 8;static constexpr uint32_t kObjectHeaderSize = kUseBrooksReadBarrier ? 24 : 16;Object.h

  3. 在中添加以下方法 Object.h

static MemberOffset TagOffset() {
    return OFFSET_OF_OBJECT_MEMBER(Object, tag);
}
Run Code Online (Sandbox Code Playgroud)
  1. 添加一个新的公共领域public: uint64_t tag;Object.h

  2. 改变

#define MIRROR_OBJECT_CLASS_OFFSET 0
ADD_TEST_EQ(MIRROR_OBJECT_CLASS_OFFSET, art::mirror::Object::ClassOffset().Int32Value())
#define MIRROR_OBJECT_LOCK_WORD_OFFSET 4
ADD_TEST_EQ(MIRROR_OBJECT_LOCK_WORD_OFFSET, art::mirror::Object::MonitorOffset().Int32Value())
#if defined(USE_BROOKS_READ_BARRIER)
#define MIRROR_OBJECT_HEADER_SIZE 16
#else
#define MIRROR_OBJECT_HEADER_SIZE 8
Run Code Online (Sandbox Code Playgroud)

#define MIRROR_OBJECT_CLASS_OFFSET 0
ADD_TEST_EQ(MIRROR_OBJECT_CLASS_OFFSET, art::mirror::Object::ClassOffset().Int32Value())
#define MIRROR_OBJECT_LOCK_WORD_OFFSET 4
ADD_TEST_EQ(MIRROR_OBJECT_LOCK_WORD_OFFSET, art::mirror::Object::MonitorOffset().Int32Value())
#define MIRROR_OBJECT_CLASS_TAG 8
ADD_TEST_EQ(MIRROR_OBJECT_CLASS_TAG, art::mirror::Object::TagOffset().Int32Value())

#if defined(USE_BROOKS_READ_BARRIER)
#define MIRROR_OBJECT_HEADER_SIZE 24
#else
#define MIRROR_OBJECT_HEADER_SIZE 16
Run Code Online (Sandbox Code Playgroud)

asm_support.h

  1. 添加addOffset(OFFSETOF_MEMBER(mirror::Object, tag), "tag");class_linker_test.cc

Mic*_*odd 5

首先,我想声明,我认为这不是一个好主意,并且在研究目的之外可能是矫枉过正。如果您正在修改 AOSP,那么您编写的代码将取决于运行该自定义 AOSP 版本的目标设备。然而,它仍然是可能的。

我假设您已经知道如何编译自定义 AOSP 构建并将其刷写到设备上。为了编写利用新功能的代码,您还需要编译自定义 SDK。这是为了让 Android Studio 知道您的新方法存在于 中Object,并且可以针对它正确编译。完整的文档可以在这里找到,但基本上归结为:

. build/envsetup.sh
lunch sdk-eng
make sdk
Run Code Online (Sandbox Code Playgroud)

当您拥有 SDK zip 文件时,您需要将其解压缩到您的 SDKplatforms目录 - 现在它应该会在您的 SDK 管理器中显示为已选中。如果您为 SDK 提供了自定义平台 ID,那么您应该能够在您的build.gradle文件中使用它。

免责声明:这个建议纯粹是凭记忆,这是一个漫长的过程,所以我没有时间仔细检查,而且我可能错过了一些小事情。不过,这应该可以让您在大部分情况下朝着您想要的方向前进。