修改 Android 源的核心 java 库以供在应用中使用

Modify core java libraries of Android source for use in apps

我想对 Android 源做一点修改以满足我的要求。这是要求:

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

的子classes

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

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

编辑

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

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

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

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

有关

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

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

新编辑

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

  1. Object.java

    中添加新字段(例如public long tag;
  2. Object.h

    中将static constexpr uint32_t kObjectHeaderSize = kUseBrooksReadBarrier ? 16 : 8;更改为static constexpr uint32_t kObjectHeaderSize = kUseBrooksReadBarrier ? 24 : 16;
  3. Object.h中添加如下方法(仅在Android7)

static MemberOffset TagOffset() {
    return OFFSET_OF_OBJECT_MEMBER(Object, tag);
}
  1. Object.h

    中添加一个新的public字段public: uint64_t tag;
  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

#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

in asm_support.h(仅限 Android 7)

  1. class_linker_test.cc

    中添加addOffset(OFFSETOF_MEMBER(mirror::Object, tag), "tag");
  2. 改变

static_assert(kObjectHeaderSize == sizeof(mirror::HeapReference<mirror::Class>) +
                    sizeof(LockWord),

static_assert(kObjectHeaderSize == sizeof(mirror::HeapReference<mirror::Class>) +
                    sizeof(LockWord) + 8,

art/runtime/gc/collector/concurrent_copying.cc

8 在array.h

中将static constexpr size_t kFirstElementOffset = 12u;更改为static constexpr size_t kFirstElementOffset = 20u;

9 在 runtime_globals.h 中将 static constexpr size_t kObjectAlignmentShift = 3; 更改为 static constexpr size_t kObjectAlignmentShift = 4;(尚未完成)

10 次变化

static_assert(kObjectAlignment == 8, "Alignment check");
class PACKED(8) ImageHeader {

static_assert(kObjectAlignment == 16, "Alignment check");
class PACKED(16) ImageHeader {

image.h(尚未完成)

11 在gc::space::BumpPointerSpace中将static constexpr size_t kAlignment = 8;更改为static constexpr size_t kAlignment = 16;(尚未完成)

12 在device/generic/goldfish/tools/mk_combined_img.py中将#!/usr/bin/python更改为#!/usr/local/bin/python(值取决于您的/bin/env python)(仅在Android 10 )

13 变

#define DCHECK_ALIGNED_PARAM(value, alignment) \
  DCHECK(::art::IsAlignedParam(value, alignment)) << reinterpret_cast<const void*>(value)

#define DCHECK_ALIGNED_PARAM(value, alignment) \
  DCHECK(::art::IsAlignedParam(value, alignment)) << reinterpret_cast<const void*>(value) << "," << alignment

in art/libartbase/base/bit_utils.h(用于调试目的)(仅适用于Android 11)

14 次变化

DCHECK_ALIGNED_PARAM(remaining_space, object_class->GetObjectSize());
      Object* end = dst + remaining_space / object_class->GetObjectSize();

DCHECK_ALIGNED_PARAM(remaining_space, kObjectAlignment);
      Object* end = dst + remaining_space / kObjectAlignment;

in art/dex2oat/linker/image_writer.cc(仅适用于 Android 11)

首先,我想声明,我认为这不是一个好主意,而且在研究目的之外可能有点过分了。如果您正在修改 AOSP,那么您编写的代码将取决于目标设备 运行,即定制的 AOSP 版本。不过还是可以的。

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

. build/envsetup.sh
lunch sdk-eng
make sdk

获得 SDK zip 文件后,您需要将其解压缩到 SDK 的 platforms 目录中 - 它现在应该显示在您的 SDK 管理器中。如果您为 SDK 提供了自定义平台 ID,那么您应该可以在 build.gradle 文件中使用它。

免责声明:这个建议纯属凭记忆,过程比较长所以没来得及复查,可能会有一些小问题我错过的事情。不过,这应该能让您顺利到达您想去的地方。