通过更改libcore的Runtime.class来公开新的ART功能

时间:2015-10-21 21:50:09

标签: java android c++ android-source android-runtime

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

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

我已使用Runtime.java函数以类似的方式编辑libcore/luni中的java_lang_Runtime.ccart中的gc()。我正在生成新的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")

该设备位于bootloop上。我应该编辑其他文件吗?我应该在设备上构建额外的模块,还是发送任何其他文件?

顺便说一句,我不想​​为调用SDK构建新的myMethod我会将Dalvik bytecode注入到APK文件中。基本上我将获取Runtime实例,然后调用该方法。

1 个答案:

答案 0 :(得分:0)

问题:

Android通过预先优化的框架组件发布工厂映像。 文件boot.oat包含预优化的代码(或odex代码),可以通过读取boot.art文件中包含的指针来访问它。

这两个文件仅包含boot classpath的代码。 框架的其余部分以及其他系统应用程序(在apppriv-app)文件夹中都有独立的odex文件。

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

我尝试过的一些事情:

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

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

我已经尝试过闪存整个aosp生成的构建版本,但它无法正常工作,即使我使用已禁用安全功能(verity)构建的自定义内核也是如此。

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

<强>解决方案:

最后的手段是deodexing,幸好它有效。 我为Marshmallow的Nexus 6写了一个小script

该脚本在第一阶段从相关位置取出所有oat/odex代码,并将其取消优化为dex代码,这要归功于oat2dex和{{ 3}}项目。 在第二阶段,它将dex代码打包回框架模块(jars / apks)。

将全新的core-libart.jar发送到设备仍然无法正常工作(不确定原因),但在将dex文件打包到模块之前修改它们就可以了!的:))

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