通过更改 libcore 的 Runtime.class 来公开新的 ART 功能
Expose new ART functionality by changing the Runtime.class of libcore
我在 Android 运行时 (ART) 中插入了一些新功能,现在我想通过接口将其公开给外界。由于它是本机代码,我将使用 JNI
接口来调用此新功能,其方式与垃圾收集器功能类似:Runtime.getInstance().gc()
.
但是,我不关心构建可供 IDE 使用的新 SDK,因为我将手动将字节码注入将进行调用的 .dex 文件。
我在 libcore/luni
中编辑了 Runtime.java
,在 art
中编辑了 java_lang_Runtime.cc
,方法与 gc()
功能类似。我正在生成新的 libart.so
和 core-libart.jar
并将它们闪存到设备上。
但是,当我尝试重启设备时,我收到消息:
Failed to register native method java.lang.Runtime.myMethod()V in /system/framework/core-libart.jar
...
----- class 'Ljava/lang/Runtime;' cl=0x0 -----
vtable (24 entries, 11 in super):
// 24 entries are listed here. My entry is missing.
...
在 Runtime.java
中,我注册了本机方法并使用 @hide 在完整构建中抑制了一些警告。例如,
/** @hide */
public native void myMethod();
在 java_lang_Runtime.cc
中,我定义了函数(将调用 ART 内部的东西)并使用宏将其注册到 gMethods[] 数组。例如,
static void Runtime_myMethod(JNIEnv*, jclass) {
// body
}
NATIVE_METHOD(Runtime, myMethod, "()V")
设备处于引导循环中。还有其他我应该编辑的文件吗?我应该构建额外的模块,还是在设备上发送任何其他文件?
顺便说一句,我不想构建一个新的 SDK
至于调用 myMethod
我会将 Dalvik bytecode
注入到一个 APK 文件中。基本上我会获取Runtime实例,然后调用方法。
问题:
Android 出厂图像与框架组件进行了预优化。
文件 boot.oat
包含预先优化的代码(或 odex 代码),可以通过读取 boot.art
文件中包含的指针来访问这些代码。
这两个文件仅包含 boot classpath
的代码。
框架的其余部分和系统应用程序的其余部分(在 app
和 priv-app
中)文件夹具有独立的 odex
文件。
在这个预优化阶段,dex代码被取出的框架模块(jar,或apk),使用dex2oat
编译,生成的代码位于我刚才提到的文件中。
我试过的一些东西:
仅运送 libart.so
和 core-libart.jar
不起作用,即使后者包含 dex 代码。这是因为 运行time 仍在尝试从 boot.oat
.
中读取该信息
通过修改设备配置做预优化,aosp build system
可以生成boot.oat|art
和其余的odex
文件(更多here)。我预计闪烁所有这些应该工作,但它没有。
(至少对于 marshmallow-release
分支,在 nexus6 上)
我试过刷新整个 aosp 生成的构建,但它没有用,即使我构建的自定义内核禁用了安全功能 (verity
)。
我确信其中一些应该有效,但在构建 OS.
期间必须考虑其他一些事情
解法:
最后的手段是 deodexing
,谢天谢地,它奏效了。
我写了一个小的 script 用于 Marshmallow 上的 Nexus 6。
脚本,在第一阶段,它从相关位置取出所有 oat/odex
代码,并将其取消优化为 dex
代码,感谢 oat2dex and smali 项目.
在第二阶段,它将 dex
代码打包回框架模块 (jars/apks).
将全新的 core-libart.jar
发送到设备仍然无法正常工作(不知道为什么),但是在将 dex 文件打包到模块之前修改它们就可以了! :))
libart.so
现在可以找到 Runtime.myMethod()
,它可以被应用程序调用(smali 再次修补)到 运行 我在 ART
.[=36 中的代码=]
我在 Android 运行时 (ART) 中插入了一些新功能,现在我想通过接口将其公开给外界。由于它是本机代码,我将使用 JNI
接口来调用此新功能,其方式与垃圾收集器功能类似:Runtime.getInstance().gc()
.
但是,我不关心构建可供 IDE 使用的新 SDK,因为我将手动将字节码注入将进行调用的 .dex 文件。
我在 libcore/luni
中编辑了 Runtime.java
,在 art
中编辑了 java_lang_Runtime.cc
,方法与 gc()
功能类似。我正在生成新的 libart.so
和 core-libart.jar
并将它们闪存到设备上。
但是,当我尝试重启设备时,我收到消息:
Failed to register native method java.lang.Runtime.myMethod()V in /system/framework/core-libart.jar
...
----- class 'Ljava/lang/Runtime;' cl=0x0 -----
vtable (24 entries, 11 in super):
// 24 entries are listed here. My entry is missing.
...
在 Runtime.java
中,我注册了本机方法并使用 @hide 在完整构建中抑制了一些警告。例如,
/** @hide */
public native void myMethod();
在 java_lang_Runtime.cc
中,我定义了函数(将调用 ART 内部的东西)并使用宏将其注册到 gMethods[] 数组。例如,
static void Runtime_myMethod(JNIEnv*, jclass) {
// body
}
NATIVE_METHOD(Runtime, myMethod, "()V")
设备处于引导循环中。还有其他我应该编辑的文件吗?我应该构建额外的模块,还是在设备上发送任何其他文件?
顺便说一句,我不想构建一个新的 SDK
至于调用 myMethod
我会将 Dalvik bytecode
注入到一个 APK 文件中。基本上我会获取Runtime实例,然后调用方法。
问题:
Android 出厂图像与框架组件进行了预优化。
文件 boot.oat
包含预先优化的代码(或 odex 代码),可以通过读取 boot.art
文件中包含的指针来访问这些代码。
这两个文件仅包含 boot classpath
的代码。
框架的其余部分和系统应用程序的其余部分(在 app
和 priv-app
中)文件夹具有独立的 odex
文件。
在这个预优化阶段,dex代码被取出的框架模块(jar,或apk),使用dex2oat
编译,生成的代码位于我刚才提到的文件中。
我试过的一些东西:
仅运送 libart.so
和 core-libart.jar
不起作用,即使后者包含 dex 代码。这是因为 运行time 仍在尝试从 boot.oat
.
通过修改设备配置做预优化,aosp build system
可以生成boot.oat|art
和其余的odex
文件(更多here)。我预计闪烁所有这些应该工作,但它没有。
(至少对于 marshmallow-release
分支,在 nexus6 上)
我试过刷新整个 aosp 生成的构建,但它没有用,即使我构建的自定义内核禁用了安全功能 (verity
)。
我确信其中一些应该有效,但在构建 OS.
期间必须考虑其他一些事情解法:
最后的手段是 deodexing
,谢天谢地,它奏效了。
我写了一个小的 script 用于 Marshmallow 上的 Nexus 6。
脚本,在第一阶段,它从相关位置取出所有 oat/odex
代码,并将其取消优化为 dex
代码,感谢 oat2dex and smali 项目.
在第二阶段,它将 dex
代码打包回框架模块 (jars/apks).
将全新的 core-libart.jar
发送到设备仍然无法正常工作(不知道为什么),但是在将 dex 文件打包到模块之前修改它们就可以了! :))
libart.so
现在可以找到 Runtime.myMethod()
,它可以被应用程序调用(smali 再次修补)到 运行 我在 ART
.[=36 中的代码=]