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 ⚠️

已知问题

  1. 约定被系统性违反:shared/ 下 4 个变换类中有 3 个依赖 gtnhlib / ASM / log4j,AngelicaClassDump 还依赖 glsm 与 RFB API。package-info 的「不得引用包外代码」在本仓库里几乎没有实际遵守。
  2. 约定与现实脱节的合理解释:注释里留了口子 ——「unless the code is known to be safe with different classloaders」。gtnhlib / ASM / log4j 由两个 loader 共同可见(它们在 classpath 根部),所以实践上安全。但「known to be safe」没有任何检查工具或测试保障,纯粹靠人判断。
  3. 真正的风险点是 SystemProperties 与 ClassDump:这两个在 glsm 子项目里,物理路径 glsm/src/main/java/...。它们被打进最终 jar 后是普通 class,所以 AngelicaClientTweaker :10 的 import 才能工作。但源码树位置与逻辑归属的错位,正是这种约定的直接成本(见 §④ 裁定)。
  4. 未说明「RFB 与 FML 如何共享同一份 shared/ 类」:注释说「may be loaded both by」,但没解释是同一个 loader 还是两个。若 RFB 与 LaunchWrapper 在同一 JVM 里各加载一份 shared/ 类,则 AngelicaClassDump.INSTANCE 会有两个单例副本,:9 的 DUMP_CLASS 开关各读一次——这本身无害,但 CeleritasBlockTransform 的 Collections.newSetFromMap(new ConcurrentHashMap<>()) 静态集合则会各持一份,跟踪状态不共享。仓库内无说明。

相关条目