android sharedUserId 使用知识盲点解析

 更新时间:2023年02月15日 08:40:10   作者:Exploring  
这篇文章主要为大家介绍了android sharedUserId使用的知识盲点解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

1. 背景

由于在工程中使用了 SPI 机制,通过 ServiceLoader 的配合来完成模块间的通信。但是突然收到线上客户反馈使用了 SDK 后无法进行模块加载,导致部分功能异常。

2. 分析排查

借助客户提供的测试包进行 debug 调试,发现在调试到 ServiceLoader.load() 方法时确实无法加载到对应的模块配置。查看 ServiceLoader 的状态信息如下:

其中的 loader 是 LoadApk$WarningContextClassLoader 对象,而正常情况下是 DexPathClassLoader。

2.1 查看 ServiceLoader.loader 定义

ServiceLoader API 文档:developer.android.com/reference/j…

根据接口定义 load 方法会根据指定的 serviceType 创建新的 ServiceLoader 对象返回,ServiceLoader 内部根据当前线程对应的 ContextClassLoader 对象去加载配置,所以到这里可以分析到 load 方法的加载结果会受 ContextClassLoader 的影响,进一步推理可能收到插件化、热修复等框架影响,确认后并没有使插件化、热修复等框架。

2.2 WarningContextClassLoader 为何物?

查找 Android famework 源码,找到 WarningContextClassLoader 是定义在 LoaderApk 文件中的内部类(部分版本是 ActivityThread 类中的内部类)。

private void initializeJavaContextClassLoader() {
	IPackageManager pm = ActivityThread.getPackageManager();
	android.content.pm.PackageInfo pi =
			PackageManager.getPackageInfoAsUserCached(
					mPackageName,
					PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
					UserHandle.myUserId());
	if (pi == null) {
		throw new IllegalStateException("Unable to get package info for "
				+ mPackageName + "; is package not installed?");
	}
	/*
	 * Two possible indications that this package could be
	 * sharing its virtual machine with other packages:
	 *
	 * 1.) the sharedUserId attribute is set in the manifest,
	 *     indicating a request to share a VM with other
	 *     packages with the same sharedUserId.
	 *
	 * 2.) the application element of the manifest has an
	 *     attribute specifying a non-default process name,
	 *     indicating the desire to run in another packages VM.
	 */
	boolean sharedUserIdSet = (pi.sharedUserId != null);
	boolean processNameNotDefault =
		(pi.applicationInfo != null &&
		 !mPackageName.equals(pi.applicationInfo.processName));
	boolean sharable = (sharedUserIdSet || processNameNotDefault);
	ClassLoader contextClassLoader =
		(sharable)
		? new WarningContextClassLoader()
		: mClassLoader;
	Thread.currentThread().setContextClassLoader(contextClassLoader);
}
private static class WarningContextClassLoader extends ClassLoader {
	private static boolean warned = false;
	private void warn(String methodName) {
		if (warned) {
			return;
		}
		warned = true;
		Thread.currentThread().setContextClassLoader(getParent());
		Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
			  "The class loader returned by " +
			  "Thread.getContextClassLoader() may fail for processes " +
			  "that host multiple applications. You should explicitly " +
			  "specify a context class loader. For example: " +
			  "Thread.setContextClassLoader(getClass().getClassLoader());");
	}
	...
}

在应用创建时会调用 ActivityThread 类中的 attach 方法中,attach 方法进而调用 LoadedApk 类中的 makeApplicationInner() 用于创建对应的 Application 对象。在 makeApplicationInner() 方法的内部调用 initializeJavaContextClassLoader 方法创建对应的 ContentClassLoader 对象,在 initializeJavaContextClassLoader 方法的内部可以看到,如果当前 App 在 manifest 中设置 sharedUserId 属性,则当前应用使用的是 WarningContextClassLoader。下面我们就是查看 App 中的配置。

最终验证了我们的猜想,使用 demo 设置 sharedUserId 属性问题可正常复现。

2.3 sharedUserId 属性

查看官方文档该属性配置 API 级别 29 中已弃用此常量。共享用户 ID 会在软件包管理器中导致具有不确定性的行为。因此,强烈建议您不要使用它,并且我们在未来的 Android 版本中会将其移除。

2.总结

排查问题还是比较费神,在没有明显错误的时候,只能针对每个可疑的信息去分析,期望发现蛛丝马迹。

以上就是android sharedUserId 使用知识盲点解析的详细内容,更多关于android sharedUserId 知识盲点的资料请关注脚本之家其它相关文章!

相关文章

  • Android互联网访问图片并在客户端显示的方法

    Android互联网访问图片并在客户端显示的方法

    这篇文章主要介绍了Android互联网访问图片并在客户端显示的方法,结合实例分析了Android处理图片的技巧,并附带了Android的URL封装类,网络连接封装类与输出流封装类,需要的朋友可以参考下
    2015-12-12
  • Android中WebView用法实例分析

    Android中WebView用法实例分析

    这篇文章主要介绍了Android中WebView用法,以实例形式较为详细的分析了Android中WebView的功能、注意事项与使用技巧,非常具有实用价值,需要的朋友可以参考下
    2015-10-10
  • Android动态修改ToolBar的Menu菜单示例

    Android动态修改ToolBar的Menu菜单示例

    本篇文章主要介绍了Android动态修改ToolBar的Menu菜单示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • Android仿网易客户端顶部导航栏效果

    Android仿网易客户端顶部导航栏效果

    这篇文章主要为大家详细介绍了Android仿网易客户端顶部导航栏效果,帮助大家制作网易客户端导航栏特效,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • Android实现绚丽的自定义进度条

    Android实现绚丽的自定义进度条

    进度条是在Android项目中很常用的组件之一,本文将为大家详细地介绍一下自定义进度条的实现过程。感兴趣的小伙伴可以跟随小编一起学习一下
    2022-01-01
  • Android实现仿微软系统加载动画效果

    Android实现仿微软系统加载动画效果

    这篇文章主要介绍了Android实现仿微软系统加载动画效果的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下
    2021-04-04
  • Kotlin Job启动流程源码层深入分析

    Kotlin Job启动流程源码层深入分析

    如果要我拿现实中的一事物与Kotlin协程中的Job做一个类比,那么我会把Job比作成海洋中的冰山。自由漂浮的冰山约有90%体积沉在海水表面下,因此看着浮在水面上的形状并猜不出水下的形状
    2022-11-11
  • Android远程服务编写和调用教程

    Android远程服务编写和调用教程

    这篇文章主要介绍了Android远程服务编写和调用教程,本文教大家如何编写或者调用Android的远程服务,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • Intent传递对象之Serializable和Parcelable的区别

    Intent传递对象之Serializable和Parcelable的区别

    Intent在不同的组件中传递对象数据的应用非常普遍,大家都知道在intent传递对象的方法有两种:1、实现Serializable接口、2、实现Parcelable接口,接下来通过本文给大家介绍Intent传递对象之Serializable和Parcelable的区别,感兴趣的朋友一起学习吧
    2016-01-01
  • Eclipse新建Android项目报错解决方案详细汇总

    Eclipse新建Android项目报错解决方案详细汇总

    这篇文章主要介绍了Eclipse新建Android项目报错解决方案详细汇总,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08

最新评论