反射访问点
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。
相关条目
- MCLib 核心与任务队列 -
FML_MASTER的取得 - 多版本原版资源包 -
defaultResourcePacks注入的实际效果 - AssetFetcher - 使用
MCUtil.getMCAssetsDir()作为下载目标根