ForgelinSetup 预载钩子

基本信息

属性 值
所属 Forgelin(modid forgelin)
类型 IFMLCallHook 实现
源码 preloader/ForgelinSetup.kt:8
调用方 ForgelinPlugin.getSetupClass()(ForgelinPlugin.kt:22)

作用

在 FML 的类加载早期,用真实 ClassLoader 显式加载一次 KotlinAdapter。 目的是让 Kotlin 运行时(以及被 shadow 打包进来的 kotlinx-coroutines) 在任何 mod 的类被加载之前完成初始化,避免 NoClassDefFoundError。

override fun injectData(data: Map<String?, Any?>?) {
    val loader = data?.get("classLoader") as ClassLoader?
    try {
        loader?.loadClass("net.shadowfacts.forgelin.KotlinAdapter")
    } catch (e: ClassNotFoundException) {
        // this should never happen
        throw RuntimeException("Couldn't find Forgelin language adapter, this shouldn't be happening", e)
    }
}

(ForgelinSetup.kt:9-17)

call() 返回 null(行 19-22),即注册到 List<FMLCallHook> 后不执行任何后置动作, 本类的全部作用就是 injectData 里那一行 loadClass。

与 FML 数据类的关系

injectData 从传入的 Map 里取 "classLoader" 键,类型断言为 ClassLoader?。 该 Map 由 FML 构造,键名与 ForgelinPlugin 收到的 injectData 是同一份。源码用 as(非 as?)强转,若该键缺失会抛 NullPointerException 而非给出可读错误。

已知源码问题

  • loader 为 null 时静默跳过:使用了安全调用 loader?.loadClass(...), 若 data 为 null 或键不存在,预载会被无声跳过,类初始化时机退回默认行为。 与 ForgelinAutomaticEventSubscriber.kt:28 的静默早退是同一类问题。
  • RuntimeException 包装掩盖根因:注释写 “this should never happen”, 抛出后 FML 只会看到一条 Forgelin 自己的异常,原始 ClassNotFoundException 作为 cause 挂在下面。
  • @Throws(Exception::class) 标注在 call() 上(行 19),但该方法实际不抛任何异常, 属冗余声明。

相关条目