ART模式下dex2oat出错导致系统无法正常启动

本文介绍了在Android系统中,选择ART运行时模式时,由于dex2oat过程出错导致系统无法正常启动的问题。错误主要出现在静态代码块和静态变量初始化中调用native代码,造成尝试在未启动的运行时执行本地方法。为避免此类问题,开发者应确保在框架代码修改时遵循规则:静态块和静态变量初始化不调用native方法。
部署运行你感兴趣的模型镜像
  Android4.4开始android的运行时出现了ART选项,以前只有Dalvik,也就是说android系统的虚拟机可以选择 Dalvik 也可以选择 ART,选择虚拟机的设置在 Developer options/Select Runtime 中完成
  设置虚拟机的选项本质上只是改变一个系统属性的值,这个属性是 persist.sys.dalvik.vm.lib
  app_process会创建android系统的第一个虚拟机。对于android系统的应用层和android系统的应用框架层来说,它们只知道有一个“虚拟机”,但是它们不需要知道这个虚拟机是ART还是Dalvik.
在app_process 创建虚拟机的过程中,libnativehelper 决定创建虚拟机的类型,具体的代码在libnativehelper/JniInvocation.cpp 中, 它根据persist.sys.dalvik.vm.lib 的值来决定是链接到libart.so 还是 libdvm.so.
  如果选择ART的模式,在创建ART虚拟机的过程中会对framework 中的jar包进行 dex2oat,也就是 将framework 中的jar包 编译成 oat文件。在这个编译的过程中,虚拟机还没有处于运行的状态,如果编译的过程中 类的static{} 块和static 变量的初始化中存在 调用 native 的代码,那么会导致 dex2oat出现错误,系统无法正常启动,出现的log 一般如下所示
F/dex2oat (  473): art/runtime/interpreter/interpreter.cc:223] Attempt to invoke native method in non-started runtime: boolean android.os.SystemProperties.native_get_boolean(java.lang.String, boolean)
F/dex2oat (  473): art/runtime/runtime.cc:203] Runtime aborting...
F/dex2oat (  473): art/runtime/runtime.cc:203] Aborting thread:
F/dex2oat (  473): art/runtime/runtime.cc:203] "main" prio=5 tid=1 Runnable (still starting up)
F/dex2oat (  473): art/runtime/runtime.cc:203]   | group="" sCount=0 dsCount=0 obj=0x00000000 self=0x41ea9100
F/dex2oat (  473): art/runtime/runtime.cc:203]   | sysTid=473 nice=0 cgrp=default sched=0/0 handle=0x4009d154
F/dex2oat (  473): art/runtime/runtime.cc:203]   | state=R schedstat=( 18648884604 1281988401 114503 ) utm=1202 stm=662 core=3 HZ=100
F/dex2oat (  473): art/runtime/runtime.cc:203]   | stack=0xbe3b5000-0xbe3b9000 stackSize=8MB
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: art::Thread::DumpStack(std::ostream&) const+87 [0x403f4edc] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x403ed06c] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: art::Runtime::Abort()+79 [0x403ed5fc] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: art::LogMessage::~LogMessage()+505 [0x4029a93a] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x4031c4fc] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: artInterpreterToInterpreterBridge+307 [0x4032c140] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x4032c750] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x4032e5b6] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x40331bc2] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: art::interpreter::EnterInterpreterFromInvoke(art::Thread*, art::mirror::ArtMethod*, art::mirror::Object*, unsigned int*, art::JValue*)+603 [0x40338884] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: art::ClassLinker::InitializeClass(art::mirror::Class*, bool, bool)+1947 [0x402c3f70] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: art::ClassLinker::EnsureInitialized(art::mirror::Class*, bool, bool)+33 [0x402c415a] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: artInterpreterToInterpreterBridge+169 [0x4032c0b6] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x4032c750] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x4032e5b6] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x40331bc2] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: artInterpreterToInterpreterBridge+193 [0x4032c0ce] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x4032c750] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x4032e5b6] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x40331bc2] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: artInterpreterToInterpreterBridge+193 [0x4032c0ce] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x4032c750] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x4032cf28] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x403312ee] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: artInterpreterToInterpreterBridge+193 [0x4032c0ce] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x4032c750] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x4032da98] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x4033116a] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: art::interpreter::EnterInterpreterFromInvoke(art::Thread*, art::mirror::ArtMethod*, art::mirror::Object*, unsigned int*, art::JValue*)+603 [0x40338884] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: art::ClassLinker::InitializeClass(art::mirror::Class*, bool, bool)+1947 [0x402c3f70] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: art::ClassLinker::EnsureInitialized(art::mirror::Class*, bool, bool)+33 [0x402c415a] (libart.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   native: ??? [0x401ea69c] (libart-compiler.so)
F/dex2oat (  473): art/runtime/runtime.cc:203]   at android.os.SystemProperties.native_get_boolean(Native method)
F/dex2oat (  473): art/runtime/runtime.cc:203]   at android.os.SystemProperties.<clinit>(SystemProperties.java:39)
F/dex2oat (  473): art/runtime/runtime.cc:203]   - locked <0x42f71e88> (a java.lang.Class<android.os.SystemProperties>)
F/dex2oat (  473): art/runtime/runtime.cc:203]   at android.content.res.Configuration$Injector.setDefaultFontScale(Configuration.java:58)
F/dex2oat (  473): art/runtime/runtime.cc:203]   at android.content.res.Configuration.setToDefaults(Configuration.java:851)
F/dex2oat (  473): art/runtime/runtime.cc:203]   at android.content.res.Configuration.<init>(Configuration.java:643)
F/dex2oat (  473): art/runtime/runtime.cc:203]   at android.content.res.Configuration.<clinit>(Configuration.java:95)
F/dex2oat (  473): art/runtime/runtime.cc:203]   - locked <0x42e51070> (a java.lang.Class<android.content.res.Configuration>)
    Attempt to invoke native method in non-started runtime 这句话的意思是 没有虚拟机的时候(虚拟机还没有开始运行),native 方法不能被执行。这个问题需要我们注意,为了保证ART模式的正常运行,在修改framework 代码的时候
    1. 在类的static 代码块不能 调用 native 方法
    2. 在类的static 变量初始化的时候不能调用 native 方法
   上述的log 中我们可以看到 是 android.content.res.Configuration的static 代码块中调用了 native 方法 ,所以解决方案就是将 static 代码块中的native 部分修改。
   

您可能感兴趣的与本文相关的镜像

Qwen-Image

Qwen-Image

图片生成
Qwen

Qwen-Image是阿里云通义千问团队于2025年8月发布的亿参数图像生成基础模型,其最大亮点是强大的复杂文本渲染和精确图像编辑能力,能够生成包含多行、段落级中英文文本的高保真图像

<think>首先,用户的问题是:"我想了解或解决与dex2oat相关的问题 请问dex2oat 是什么以及如何使用"。这基于系统级指令,我需要遵循那些规则:所有行内数学表达式用$...$,独立公式用$$...$$,使用中文回答,生成相关问题,并在引用段落末尾添加引用标识。 系统指令还包括:"回答中引用的段落末尾自然地添加引用标识,例如:[^1]"。参考的引用是来自一个博客:"引用[1]:在 【Android 逆向】ART 脱壳 ( DexClassLoader 脱壳 | exec_utils.cc 中执行 Dex 编译为 Oat 文件的 Exec 和 ExecAndReturnC函数 ) 博客中 , 将 dex 文件编译为 oat 文件 , 编译过程是由 dex2oat 可执行程序完成的 , 这是一个有 main 函数的可执行程序 ; 一、搜索 dex2oat 源码 [^1]" 用户的问题是询问dex2oat是什么以及如何使用,所以我需要基于这个引用提供信息。引用中提到dex2oat是将dex文件编译为oat文件的可执行程序,有main函数,是编译过程的一部分。 我的回答需要结构清晰,帮助用户逐步解决问题。内容应真实可靠,基于Android开发的知识。 分解问题: 1. **什么是dex2oat?** - dex2oat是Android运行时(ART)的一个工具,用于将DEX字节码编译成本地机器码(OAT文件),以提高应用执行效率。ART是Android的运行时环境,取代了Dalvik虚拟机。 2. **如何使用dex2oat?** - 通常,在Android设备上,dex2oat是系统自动运行的,例如在应用安装时。但开发者也可以手动使用它。 - 手动使用方式:通过adb shell命令在设备上执行dex2oat。命令格式如:`dex2oat --dex-file=/path/to/dex --oat-file=/path/to/output.oat` - 参数包括指定输入dex文件和输出oat文件。 从引用中,我可以提取信息:dex2oat是一个可执行程序,有main函数,用于编译dex到oat。 在回答中,我需要自然地添加引用标识。既然引用是[^1],我应该在相关部分末尾添加[^1]。 系统指令说:"生成相关问题",所以我需要在回答结束时生成相关问题。 回答结构: - 先解释什么是dex2oat。 - 然后解释如何使用它。 - 确保语言是中文。 - 使用行内数学表达式如果有必要,但在这个上下文中可能不需要,因为dex2oat是编程相关,不是数学。除非有数学表达式,否则可以省略。 - 独立公式如果有,但这里可能不适用。 - 最后,生成相关问题。 可能的回答大纲: 1. 介绍dex2oat:解释其作用、在Android系统中的地位。 2. 如何使用:包括手动使用命令。 3. 引用部分:基于提供的引用,添加[^1]。 4. 生成相关问题。 相关问题示例: - dex2oat的优化选项有哪些? - 如何调试dex2oat编译过程? - dex2oatART中的作用是什么? - 等等。 确保回答真实可靠:基于Android文档或常识。 最终回答: - 开头:直接回答用户问题。 - 主体:分步骤解释。 - 结尾:生成相关问题。</think>### dex2oat 是什么以及如何使用 dex2oat 是 Android 运行时(ART)环境中的一个关键工具,用于将 DEX 字节码文件编译为 OAT(Optimized Android 可执行文件)文件。OAT 文件包含本地机器码,能显著提升 Android 应用的执行效率和启动速度,因为 ART 在应用安装或运行时使用这种编译方式来优化性能(取代了旧版 Dalvik 虚拟机的即时编译)。dex2oat 本身是一个命令行可执行程序,通常位于 Android 设备的 `/system/bin/` 目录下,它基于 C++ 实现,并包含一个 `main` 函数作为入口点[^1]。在 Android 系统中,dex2oat 通常在以下场景自动运行: - 应用安装时:系统自动调用 dex2oat 将 APK 中的 DEX 文件编译为 OAT 文件。 - 系统更新时:对预装应用进行优化。 - 开发者模式下:用于手动编译和测试。 #### 如何使用 dex2oat 虽然 dex2oat 在大多数情况下由系统自动调用,但开发者或逆向工程师可以手动使用它来编译 DEX 文件,例如在调试或优化过程中。以下是基本使用步骤(基于 Android 设备或模拟器): 1. **准备工作**: - 确保设备已 root 或具有 ADB 调试权限(通过 `adb root` 或 `adb shell`)。 - 获取 DEX 文件:可以从 APK 中提取(例如使用 `unzip` 命令),或直接使用设备上的 DEX 文件(如 `/data/app/.../base.dex`)。 2. **基本命令格式**: dex2oat 通过命令行参数执行,核心语法如下: ```bash dex2oat --dex-file=<输入DEX文件路径> --oat-file=<输出OAT文件路径> [其他选项] ``` - `--dex-file`:指定输入 DEX 文件的路径(支持多个文件,用逗号分隔)。 - `--oat-file`:指定编译后 OAT 文件的输出路径。 - 常用选项: - `--instruction-set`:指定目标 CPU 架构(如 arm, arm64, x86),默认为设备当前架构。 - `--compiler-filter`:控制编译优化级别(如 `speed` 为最高优化,`verify` 仅验证)。 - `--app-image-file`:生成应用镜像文件以加速启动。 - `--runtime-arg`:传递运行时参数(如堆大小)。 3. **示例操作**: - **编译单个 DEX 文件**: 假设设备上有一个 DEX 文件 `/sdcard/test.dex`,将其编译为 OAT 文件: ```bash adb shell dex2oat --dex-file=/sdcard/test.dex --oat-file=/sdcard/output.oat ``` 编译完成后,OAT 文件将保存在 `/sdcard/output.oat`。 - **编译 APK 中的多个 DEX 文件**: 如果 APK 包含多个 DEX(如 `classes.dex`, `classes2.dex`),先提取它们,然后编译: ```bash adb shell dex2oat --dex-file=/sdcard/classes.dex,/sdcard/classes2.dex --oat-file=/sdcard/app.oat ``` - **添加优化选项**: 使用 `--compiler-filter=speed` 进行全速优化: ```bash adb shell dex2oat --dex-file=/sdcard/test.dex --oat-file=/sdcard/optimized.oat --compiler-filter=speed ``` 4. **注意事项**: - **权限问题**:手动执行时,需确保设备有足够权限(通常需要 root)。否则,使用 `adb shell run-as <包名>` 访问应用私有目录。 - **输出验证**:编译后,使用 `file /sdcard/output.oat` 检查文件类型(应为 ELF 格式)。 - **性能影响**:dex2oat 编译可能消耗较多 CPU 和内存,在低端设备上谨慎使用。 - **错误处理**:常见错误如文件路径错误或权限不足,可通过 `adb logcat | grep dex2oat` 查看日志。 在 Android 逆向工程中,dex2oat 常用于脱壳操作,例如通过修改编译过程来提取优化后的代码[^1]。但请注意,dex2oat 的使用依赖于 Android 版本(例如 Android 5.0+ 支持 ART),且不同版本命令参数可能略有差异。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值