当前位置: 首页 > ops >正文

【Android】从一个AndroidRuntime看类的加载

app中如果存在一个和系统中同名的jar包,在执行的时候会使用系统的jar,下面的crash就是在系统的jar中没有找到相应的方法,出现的AndroidRuntime异常

01-14 16:23:48.484  3969  3969 E AndroidRuntime: Process: com.example.testapp, PID: 3969

01-14 16:23:48.484  3969  3969 E AndroidRuntime: java.lang.NoSuchMethodError: No interface method setData(ILandroid/os/ParcelFileDescriptor;)I in class Lcom/test/ITestManager; or its super classes (declaration of 'com.test.ITestManager' appears in /system/framework/miscmdm.jar)

在 Android 系统中,“系统中的 JAR 覆盖 App 中的同名 JAR” 这种说法并不完全准确,需要从 Android 的类加载机制、系统类库和应用类路径的设计来理解其背后的原理。

简单来说:不是“覆盖”,而是系统类优先加载,应用无法重新定义系统已提供的类。


一、Android 的类加载机制

Android 使用的是 DexClassLoader(或其父类 BaseDexClassLoader)来加载 .dex 文件或 .apk 中的类。它遵循 双亲委派模型(Parent Delegation Model),但略有不同。

类加载顺序大致如下:

  1. BootClassLoader(系统引导类加载器)
    • 加载系统核心类库(如 android.jarcore-oj.jar 等)
    • 这些类在 /system/framework/ 目录下
  2. PathClassLoader / DexClassLoader
    • 加载应用自身的 .dex 文件(即你的 APK 或依赖的库)

当应用尝试加载一个类时,会先委派给父加载器(系统加载器)去查找。如果系统已经提供了这个类,就不会再加载应用中的同名类。


二、为什么“系统 JAR 优先”?

1. 系统预加载核心类库

Android 系统在启动时会预加载一系列核心 JAR 包,例如:

  • /system/framework/framework.jar
  • /system/framework/core-oj.jar
  • /system/framework/telephony-common.jar
  • 以及 OEM 厂商添加的私有 JAR

这些 JAR 包包含了 Android SDK 的实现类(不仅仅是接口),比如 Activity, Context, TelephonyManager 等。

2. 安全与稳定性

如果允许应用随意“替换”系统类(比如自己打包一个修改版的 Activity 类),就会导致:

  • 安全漏洞(可劫持系统行为)
  • 兼容性问题(不同应用使用不同版本的“系统类”)
  • 系统崩溃风险

因此,系统类是“只读”且“不可覆盖”的


三、具体例子说明

假设你有一个 JAR 文件,里面包含一个类:

package android.app;
public class Activity {// 你自定义的逻辑
}

你把这个 JAR 打包进你的 APK。

结果:

  • ✅ 编译时可能通过(因为编译用的是 android.jar,只包含方法声明)
  • ❌ 运行时:系统会使用 /system/framework/framework.jar 中真正的 android.app.Activity你打包的这个类会被忽略
  • ⚠️ 严重时可能导致 ClassNotFoundException 或 VerifyError,因为类结构不一致

四、例外情况:非系统包名的第三方库

如果你使用的是第三方库(如 okhttp, gson, rxjava),它们的包名是 com.squareup.okhttp3com.google.gson 等,不属于 android.*java.*javax.* 等系统包名空间,那么:

  • 系统没有预定义这些类
  • 应用可以自由打包和加载这些 JAR
  • 不会发生“覆盖”问题

但如果系统 ROM 厂商在 /system/framework/ 中预装了某个第三方库,而你的应用也打包了不同版本的 gson,就可能出现 类加载冲突或版本不一致问题

这种情况较少见,但某些定制 ROM 确实会这么做。


五、如何避免问题?

  1. 不要尝试替换系统类

    • 不要打包 android.*java.* 等命名空间下的类
    • 不要试图“修复”或“增强”系统类
  2. 使用 SDK 兼容方式开发

    • 使用 Support Library 或 AndroidX
    • 避免反射调用隐藏 API(除非你清楚后果)
  3. 管理第三方库版本

    • 使用 Gradle 正确管理依赖
    • 避免重复打包相同的库
    • 使用 provided 或 compileOnly 避免打包系统已提供的库
  4. 系统应用(System App)例外

    • 如果你的 APK 被烧录到 /system/priv-app/,并且签名与系统一致
    • 可能可以替换或扩展系统 JAR(需系统支持)
    • 普通应用无法做到

总结

问题解释
“系统 JAR 覆盖 App JAR”?❌ 不准确
实际机制是什么?✅ 系统类加载器优先加载系统类,应用无法重新定义系统类
为什么?安全、稳定、兼容性
能否替换系统类?❌ 普通应用不能
第三方库会冲突吗?⚠️ 一般不会,除非系统预装了同名库

结论: Android 中并不存在“系统 JAR 覆盖 App JAR”的文件级覆盖,而是 类加载机制决定了系统类优先于应用类加载。应用不能重新定义 android.* 等系统命名空间下的类,这是 Android 安全架构的一部分。

http://www.xdnf.cn/news/18634.html

相关文章:

  • 结构化智能编程:用树形向量存储重构AI代码理解范式
  • 第16届蓝桥杯C++中高级选拔赛(STEMA)2025年4月真题
  • More Effective C++ 条款05: 谨慎定义类型转换函数
  • 【Flex SerialPort】一个基于Qt6的支持自定义按键指令的串口工具
  • Kubernetes保姆级教学
  • centos搭建gitlab服务器
  • 【贪心算法】day2
  • 邮箱创建时间打标与自动删除功能设计思路
  • 13种常见机器学习算法面试总结(含问题与优质回答)
  • MySQL视图有什么用?一文读懂虚拟表的六大核心价值
  • String的最大长度剖析
  • 港口集装箱编号识别误识率↓79%!陌讯多模态融合算法落地优化
  • docker 镜像问题(解决了)
  • 第二重境:视角切换——用心灵的望远镜,看见问题的全局
  • 基于 Redis + JWT 的跨系统身份共享方案
  • Vue2+Vue3前端开发笔记合集
  • 【运维进阶】case、for、while、until语句大合集
  • VSCode+Qt+CMake详细地讲解
  • 嵌入式系统bringup通用流程
  • halcon(一)一维码解码
  • 目标检测数据集 第007期-基于yolo标注格式的茶叶病害检测数据集(含免费分享)
  • MATLAB 入门:从变量定义到基础绘图的完整上手指南
  • 05-ArkUI界面开发
  • 前端漏洞(上)- CSRF漏洞
  • C++ Core Guidelines: 最佳实践与深入解析
  • .net9 解析 jwt 详解
  • Go语言 Hello World 实例
  • RabbitMQ--消费端异常处理与 Spring Retry
  • 2025最新ncm转MP3,网易云ncm转mp3格式,ncm转mp3工具!
  • ThinkPHP8学习篇(四):请求和响应