0

我在 Android 运行时 ( ART ) 中插入了一些新功能,现在我想通过接口将其公开给外界。由于它是本机代码,我将使用JNI接口调用这个新功能,与垃圾收集器功能类似:Runtime.getInstance().gc().

但是,我不关心构建一个可供 IDE 使用的新 SDK,因为我将手动将字节码注入到 .dex 文件中以进行调用。

我已经用函数以类似的方式编辑了Runtime.javainlibcore/lunijava_lang_Runtime.ccin 。我正在生成新的并在设备上闪烁它们。但是,当我尝试重新启动设备时,我收到以下消息:artgc()libart.socore-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实例,然后调用方法。

4

1 回答 1

0

问题:

Android 在出厂映像中带有预先优化的框架组件。该文件boot.oat包含预先优化的代码(或 odex 代码),可以通过读取boot.art文件中包含的指针来访问这些代码。

这两个文件仅包含boot classpath. 框架的其余部分和系统应用程序的其余部分(在app和中priv-app)文件夹具有独立odex文件。

在此预优化阶段,dex 代码从框架模块(jar 或 apk)中取出,使用 编译dex2oat生成的代码驻留在我刚才提到的文件中。

我尝试过的一些事情:

仅发送libart.soandcore-libart.jar不起作用,即使后者包含 dex 代码。这是因为运行时仍在尝试从boot.oat.

通过修改设备配置来进行预优化,aosp build system可以生成boot.oat|art和其余odex文件(更多在这里)。我希望闪烁所有这些都应该起作用,但事实并非如此。(至少对于marshmallow-release分支,在 nexus6 上)

我尝试过刷新整个 aosp 生成的构建,但它没有工作,即使使用我构建的自定义内核verity禁用了安全功能 ()。

我确信其中一些应该有效,但在构建操作系统期间必须考虑其他一些事情。

解决方案:

最后的手段,deodexing幸运的是它奏效了。我已经为 Marshmallow 上的 Nexus 6 编写了一个小脚本

由于oat2dexsmali项目,该脚本在第一阶段oat/odex从相关位置取出所有代码,并将其反优化为dex代码。在第二阶段,它将代码打包回框架模块(jars/apks)中。dex

将一个全新core-libart.jar的设备运送到设备上仍然不起作用(不知道为什么),但是在将 dex 文件打包到模块中之前修补它们就可以了!:))

现在libart.so可以找到Runtime.myMethod(),可以由应用程序调用(再次进行小修改)以在其中运行我的代码ART

于 2015-10-26T02:24:03.870 回答