You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用字符串变量获取Kotlin类失败,常量却可行——动态特性场景

问题:动态特性模块中Class.forName使用变量参数触发ClassNotFoundException

我通过以下代码调用类方法:

val instance = Class.forName(nameClass).kotlin.objectInstance

当nameClass为常量值时,代码可以正常运行:

private const val PROVIDER_CLASS = "com.abc.xyz.feature.DynamicFeatureImpl\$Provider"

fun method() {
    val instance = Class.forName(PROVIDER_CLASS).kotlin.objectInstance
}

但当nameClass为普通字符串变量时:

fun method() {
    val nameClass = "com.abc.xyz.feature.DynamicFeatureImpl\$Provider"
    val instance = Class.forName(nameClass).kotlin.objectInstance
}

会抛出java.lang.ClassNotFoundException异常。我已通过日志确认常量与变量的值完全相同,但变量方式仍无法工作。我的目标是通过字符串变量作为参数实现该功能,请问这是什么原因?

补充说明:实际场景是通过Dagger调用动态特性模块中的方法,参考自Android开发者发布的《从动态特性模块访问代码的模式》一文。


原因分析与解决方案

核心原因:类加载器上下文差异与编译期优化

  1. 编译期常量的隐式优化:const val修饰的常量会在编译阶段被直接替换为字符串字面量,编译器可能针对动态特性模块的类加载逻辑做特殊处理,让代码能正确关联到动态模块的类加载器。而普通变量的值是运行时才确定的,无法触发这种编译期优化,导致使用的类加载器无法访问动态特性模块中的类。
  2. 类加载器的作用范围限制:动态特性模块的类由独立的类加载器管理,Class.forName()默认使用调用者所在类的类加载器(主模块类加载器)。当使用常量时,编译优化可能让代码在能访问动态模块类加载器的上下文执行;变量方式下,主模块类加载器无法加载动态模块中的类,从而抛出ClassNotFoundException。

解决方案

  1. 显式指定动态模块的类加载器
    获取动态特性模块对应的类加载器,传入Class.forName()的第三个参数,确保用正确的类加载器加载目标类:
// 示例:通过应用上下文获取动态模块类加载器(需替换为你的动态模块包名)
val dynamicModulePackageName = "com.abc.xyz.feature"
val classLoader = applicationContext.packageManager.getApplicationInfo(
    dynamicModulePackageName,
    PackageManager.GET_META_DATA
).classLoader

val nameClass = "com.abc.xyz.feature.DynamicFeatureImpl\$Provider"
val instance = Class.forName(nameClass, true, classLoader).kotlin.objectInstance

如果使用Play Core库管理动态模块,也可以通过SplitInstallManager获取已安装模块的类加载器。

  1. 确保动态模块已正确加载
    在调用Class.forName()前,确认动态特性模块已经成功下载并安装完成,避免因模块未加载导致的类找不到问题。

内容的提问来源于stack exchange,提问作者Zainal Fahrudin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 05:03:21