反射访问点

MCLib 需要读写 Minecraft / LaunchWrapper / FML 的私有字段。GTNH fork 的构建里没有任何 Access Transformer、coremod 或 mixin——所有私有字段访问都改用运行期 ReflectionHelper.getPrivateValue,靠 SRG 名兜底。

基本信息

属性 值
类型 反射 / 私有字段注入
coremod 无(gradle.properties 无 coreModClass)
Access Transformer 无(无 accessTransformersFile,仓库内无 META-INF/*_at.cfg)
Mixin 无(gradle.properties 中 enable_mixin=false;buildscript/forge-1.7-mixin.gradle 存在但仅在 nomixin 属性缺失时才 embed org.spongepowered:mixin:0.7.11-SNAPSHOT,当前项目未启用;无 mixin.*.json、无 mixinPlugin)

ReflectionHelper 调用点(逐条)

ReflectionHelper.getPrivateValue 的第三个参数是 SRG 名,混淆环境下用它查找。

声明类 字段名(读) SRG 名 用途 位置
Loader modController — 从 Loader.instance() 取出 LoadController MCLib 构造函数
LoadController masterChannel — 取出 Guava FML 母 EventBus MCLib 构造函数
Minecraft fileAssets field_110446_Y MCUtil.getMCAssetsDir() 返回 assets 目录 MCUtil.getMCAssetsDir
Minecraft defaultResourcePacks field_110449_ao 追加 MultiVersionDefaultResourcePack 到原版资源包列表 MultiVersionDefaultResourcePack.inject
SimpleReloadableResourceManager domainResourceManagers field_110548_a 取 "minecraft" 域的资源管理器 ResourcePackUtil.getMinecraftResourcePackList
FallbackResourceManager resourcePacks field_110540_a 取该域下的原版资源包列表 ResourcePackUtil.getMinecraftResourcePackList

裸 getDeclaredField 调用点

SloppyDepLoader.DepLoadInst.deleteMod 为了把已加载的旧版 jar 从类加载器中踢掉,直接反射 JDK 内部字段(没有 SRG 名,因为不是 Minecraft 类):

声明类 字段名 用途
java.net.URLClassLoader ucp 取当前类加载器的 URLClassPath
sun.net.util.URLClassPath loaders 从 loader 列表中移除目标
sun.net.util.URLClassPath lmap 从 loader 映射表里取出并 close() 掉目标

mod.delete() 失败后才走这条路;再失败则 deleteOnExit() 并报错,提示玩家手动删除。

其他反射技巧

技巧 位置 说明
LaunchClassLoader.getClassBytes("net.minecraft.world.World") DepLoadInst.addSloppyDep 返回 null 即判定为混淆环境;非混淆时才使用 SloppyDependency 的 dev 文件名
Class.forName("java.awt.Desktop") + getMethod("browse", URI.class) Util.openURLInBrowser 纯反射调用 java.awt.Desktop,避免编译期依赖 AWT
getResource("/<testClass>.class") != null DepLoadInst.addSloppyDep 通过 classloader 探测依赖是否已存在
Class.forName(pkg + "." + 相对类名) SharedLibHelper.getNewestLibPackage / findNewestLibClass 跨 shade 副本定位同一份类
Launch.blackboard SharedReference.get LaunchWrapper 全局表,跨 jar 共享状态(不是反射,但是绕过模块隔离的同类手段)

失败降级行为

ResourcePackUtil 对两次反射都做了保护:取不到 domainResourceManagers 时 LOGGER.warn("Failed to retrieve domainResourceManagers") 并退化为空 map;取不到 resourcePacks 时 LOGGER.warn("Failed to retrieve resourcePacks") 并退化为空 list。

相关条目