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

Framework.jar里的类无法通过Class.forName反射某个类的问题排查

1,背景

我们想要在system_server进程里扩展一些我们自己的功能。

考虑到解耦和编译依赖的问题,我们用PRODUCT_SYSTEM_SERVER_JARS预置我们的类,然后用反射jar里面的类的方式来实现代码引用。

2,遇到的问题

在SystemServer.java里用Class.forName可以反射到目标类。
在ParsingPackageUtils.java里用Class.forName 无法 反射到目标类。

log如下:
04-24 14:58:43.514 811 811 W PackageParsing: initSystemServerJarDemo, got exception.
04-24 14:58:43.514 811 811 W PackageParsing: at com.android.internal.pm.pkg.parsing.ParsingPackageUtils.initSystemServerJarDemo(ParsingPackageUtils.java:329)
04-24 14:58:46.120 811 811 D SystemServer: initSystemServerJarDemo, result:2

两个java里反射时,使用的是一样的方法:

    private void initSystemServerJarDemo(){String classPath = "com.demo.systemserverdemo.SystemServerDemo";try {Class classObj = Class.forName(classPath);Object obj = classObj.getDeclaredConstructor().newInstance();Method method = obj.getClass().getDeclaredMethod("test");method.setAccessible(true);int result = (int) method.invoke(obj);Slog.d(TAG, "initSystemServerJarDemo, result:"+result);} catch (Throwable ex){Slog.d(TAG, "initSystemServerJarDemo, got exception.", ex);}}

3, 问题分析

3.1,原因猜测

可能是类加载器的双亲委派机制导致的。

ParsingPackageUtils.java在framework.jar里;SystemServer.java在service.jar里。
framework.jar属于bootJar,加载顺序在service.jar之前;
framework.jar的类加载器,有可能是services.jar的父加载器。

类加载器会向当前ClassLoader和父加载器ClassLoader查找目标class;
framework.jar里的ParsingPackageUtils.java不会向子加载器查询SYSTEM_SERVER_JARS里的类;

3.2,验证结论

我们可以打印出来SystemServer.java的ClassLoader及其父加载器。
并打印出来ParsingPackageUtils.java的ClassLoader及其父加载器。
来确认类加载器对象是否存在父子关系。
使用以下方法打印类加载器信息:
private void printClassLoader(){
boolean recycle = true;
ClassLoader loader = getClass().getClassLoader();
while (recycle){
if(loader == null){
recycle = false;
return;
}
Slog.d(TAG, “initSystemServerJarDemo, loader hash:”+loader.hashCode()+“, loader class:”+loader.getClass().getName());
loader = loader.getParent();
}
}
输出如下:
04-24 15:21:27.443 806 806 D PackageParsing: initSystemServerJarDemo, loader hash:3047529, loader class:java.lang.BootClassLoader
04-24 15:21:30.883 806 806 D SystemServer: initSystemServerJarDemo, loader hash:179379372, loader class:dalvik.system.PathClassLoader
04-24 15:21:30.884 806 806 D SystemServer: initSystemServerJarDemo, loader hash:3047529, loader class:java.lang.BootClassLoader

3.3 结论

把类加载器打印出来,发现framework-PackageParsing的ClassLoader hash:3047529,
确实是SystemServer的类加载器(hash:179379372)的父类。

所以父加载器(hash:3047529)里的类,无法拿到子加载器里的东西。

因为Class.forName就是拿当前类加载器去查找类的。

libcore/ojluni/src/main/java/java/lang/Class.java

    public static Class<?> forName(String className)throws ClassNotFoundException {Class<?> caller = Reflection.getCallerClass();//当前类return forName(className, true, ClassLoader.getClassLoader(caller));}

4,改善

我们无法在framework.jar里的java类里,通过当前类加载器拿到目标类。
我们可以创建一个新的类加载器,就可以加载jar里面的类。

DexClassLoader classLoader = new DexClassLoader("/system/framework/**Demo.jar",null, null,this.class.getClassLoader());
Class classObj = classLoader.loadClass("com.demo.systemserverdemo.SystemServerDemo");
Constructor constructor = classObj.getDeclaredConstructor();
constructor.setAccessible(true);
constructor.newInstance();

--------------------------------end-----------------------------------

相关文章:

  • PCB 过孔铜厚的深入指南
  • Rust 2025:内存安全革命与异步编程新纪元
  • 解决编译pcl时报错‘chrono_literals‘: is not a member of ‘std‘
  • .NET Framework 4.0可用EXCEL导入至DataTable
  • 如何保证高防服务器中的系统安全?
  • Linux系统的延迟任务及定时任务
  • 阶段性人生答疑解惑篇:穿越市场迷雾,重构生命坐标系
  • 从数据到智慧:解密机器学习的自主学习密码
  • 下篇:深入剖析 BLE GATT / GAP / SMP 与应用层(约5000字)
  • .NET代码保护混淆和软件许可系统——Eziriz .NET Reactor 7
  • React-JSX语法
  • 第七届能源系统与电气电力国际学术会议(ICESEP 2025)
  • 深入探索RAG(检索增强生成)模型的优化技巧
  • 考研系列-计算机组成原理第二章:数据的表示和运算
  • 【UML建模】starUML工具
  • synchronized关键字的实现
  • 第二篇:Django配置及ORM操作
  • 金融软件测试有哪些注意事项?专业第三方软件测试服务机构分享
  • 【leetcode100】组合总和Ⅳ
  • AIP代码生成器——标准化接口开发智能工具
  • 专访|白俄罗斯共产党中央第一书记瑟兰科夫:只有大家联合起来,才能有效应对当前危机所带来的冲击
  • 一周文化讲座|“不一样的社会观察”
  • 为博流量编造上海车展谣言,造谣者被公安机关依法行政处罚
  • 刺激视网膜可让人“看”到全新颜色
  • 印尼塔劳群岛发生6.2级地震,震源深度140千米
  • 西安一男子在闲鱼卖手机卷入电诈案,不愿前往异地接受调查被列网逃