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

【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.dtcms.com/a/348471.html

相关文章:

  • Unreal Engine 下载与安装全指南:从入门到配置详解
  • 淘宝API实战应用:数据驱动商品信息实时监控与增长策略
  • 13种常见机器学习算法面试总结(含问题与优质回答)
  • 【209页PPT】P2ITSP新奥IT战略规划架构设计报告(附下载方式)
  • Python基础之运算符
  • Vue3 学习教程,从入门到精通,基于 Vue3 + Element Plus + ECharts + JavaScript 开发图片素材库网站(46)
  • 塔能科技物联精准节能如何构建智慧路灯免疫系统
  • 【软考选择】系分和架构哪个好考?适合什么样的人?
  • 简历书写指南
  • [创业之路-560]:机械、电气、自控、电子、软件、信息、通信、大数据、人工智能,上述技术演进过程
  • Linux shell脚本数值计算与条件执行
  • 基于php的萌宠社区网站的设计与实现、基于php的宠物社区论坛的设计与实现
  • 手写MyBatis第32弹-设计模式实战:Builder模式在MyBatis框架中的精妙应用
  • Wagtail CRX 的 Latest Pages Block 高级设置 模版v3.0 以后被阉割了
  • 基于深度学习的阿尔茨海默症MRI图像分类系统
  • CVPR2025丨遥感领域,全模态与秒超高清遥感建模重大突破,性能提升创新点
  • 人工智能-python-深度学习-自动微分
  • MySQL數據庫開發教學(二) 核心概念、重要指令
  • Run-Command:高效便捷的命令行工具
  • 46.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--集成网关--网关集成日志
  • ArticulateX:通过发音器官空间实现端到端单语语音翻译的突破
  • Vue vs React:前端框架的差异与选择
  • LabVIEW调用MATLAB 的分形生成
  • AMD KFD驱动分析系列0:HSA(异构系统架构)驱动概览
  • 海盗王3.0客户端从32位升级64位之路
  • Redis如何高效安全的遍历所有key?
  • 音视频学习(五十五):H264中的profile和level
  • DAY 55 序列预测任务介绍
  • 基于深度学习的餐盘清洁状态分类
  • 【Protues仿真】基于AT89C52单片机的温湿度测量