shared/package-info(双类加载器中立包)
基本信息
| 属性 | 值 |
|---|---|
| 文件 | src/main/java/com/gtnewhorizons/angelica/loading/shared/package-info.java |
| 行数 | 6 |
| 声明包 | com.gtnewhorizons.angelica.loading.shared |
| 性质 | 不是类 —— 只有 Javadoc + package 声明,无任何类型定义 |
唯一内容(:1-6)
3 行 Javadoc + 一行 package 声明,没有 import 与任何类型定义:
/**
* Package that contains classes that may be loaded both by RFB and FML classloaders, the code contained in this package
* should not reference any code from outside of this package to avoid causing hard to debug classloading issues unless
* the code is known to be safe with different classloaders.
*/
package com.gtnewhorizons.angelica.loading.shared;
这条约束的真实含义
Angelica 同时支持 RFB 与 经典 LaunchWrapper 两套类加载引导(见 AngelicaRfbPlugin)。两套引导器用不同的 classloader 加载 transformer。若 shared/ 里的类引用了外部类,而该外部类在两个 loader 下的可见性/初始化时机不同,就会出现 ClassCastException / NoClassDefFoundError / 初始化顺序死锁等极难排查的类加载故障。
因此约定:shared/ 下的代码默认不得引用包外任何类,除非明确知道该类在两个 loader 下都安全。
遵守情况审计
shared/ 共 6 个文件(AngelicaClassDump + 4 个 transformers/ + 本 package-info)。按 import 逐个核对:
| 类 | 包外 import | 是否安全 |
|---|---|---|
| AngelicaClassDump | SystemProperties(glsm 子项目)、ClassDump(glsm 子项目)、ClassNodeHandle(RFB API) |
⚠️ 见下 |
| AngelicaRedirector | ModRedirector(glsm)、AngelicaClassDump(同包) |
✅ |
| CeleritasBlockTransform | SystemProperties、ClassConstantPoolParser(gtnhlib)、Pair、LogManager、ASM |
⚠️ 大量包外依赖 |
| IsbrhTessellatorAbuseTransform | ClassConstantPoolParser、LogManager、ASM |
⚠️ |
| TileEntityMarkerTransform | ClassConstantPoolParser、ASM |
⚠️ |
已知问题
- 约定被系统性违反:
shared/下 4 个变换类中有 3 个依赖 gtnhlib / ASM / log4j,AngelicaClassDump还依赖 glsm 与 RFB API。package-info的「不得引用包外代码」在本仓库里几乎没有实际遵守。 - 约定与现实脱节的合理解释:注释里留了口子 ——「unless the code is known to be safe with different classloaders」。gtnhlib / ASM / log4j 由两个 loader 共同可见(它们在 classpath 根部),所以实践上安全。但「known to be safe」没有任何检查工具或测试保障,纯粹靠人判断。
- 真正的风险点是
SystemProperties与ClassDump:这两个在 glsm 子项目里,物理路径glsm/src/main/java/...。它们被打进最终 jar 后是普通 class,所以 AngelicaClientTweaker:10的 import 才能工作。但源码树位置与逻辑归属的错位,正是这种约定的直接成本(见 §④ 裁定)。 - 未说明「RFB 与 FML 如何共享同一份
shared/类」:注释说「may be loaded both by」,但没解释是同一个 loader 还是两个。若 RFB 与 LaunchWrapper 在同一 JVM 里各加载一份shared/类,则AngelicaClassDump.INSTANCE会有两个单例副本,:9的DUMP_CLASS开关各读一次——这本身无害,但CeleritasBlockTransform的Collections.newSetFromMap(new ConcurrentHashMap<>())静态集合则会各持一份,跟踪状态不共享。仓库内无说明。
相关条目
- fml/tweakers/package-info - 另一个
package-info,约束内容完全不同 - AngelicaClassDump -
shared/的门面类 - AngelicaRfbPlugin - 双路径的来源
- Subprojects(内嵌子项目) - glsm 子项目
- SystemProperties - 物理文件在 glsm 子项目内