ThreadSafeISBRHAnnotationTransformer

基本信息

属性 值
类 ...loading.fml.compat.transformers.generic.ThreadSafeISBRHAnnotationTransformer
路径 src/main/java/com/gtnewhorizons/angelica/loading/fml/compat/transformers/generic/ThreadSafeISBRHAnnotationTransformer.java
行数 20
类型 public class(:8),不实现 IClassTransformer
入口签名 public static void transform(ClassNode cn, boolean perThread)(:10)
注入的注解 Lcom/gtnewhorizons/angelica/api/ThreadSafeISBRH;(:15)

它是什么

4 个 generic/ transformer 里最简单的:整个类只有一个方法,只做一件事——往目标类上贴一个运行时注解,不改任何指令。被 GenericCompatTransformer :78-80 调用。

完整实现(:10-19)

public static void transform(ClassNode cn, boolean perThread) {
    if (cn.visibleAnnotations == null) {
        cn.visibleAnnotations = new ArrayList<>();
    }
    AnnotationNode isbrhAnnotation = new AnnotationNode("Lcom/gtnewhorizons/angelica/api/ThreadSafeISBRH;");
    isbrhAnnotation.values = Arrays.asList("perThread", perThread);
    cn.visibleAnnotations.add(isbrhAnnotation);
}

只写 visibleAnnotations(运行时可见),不碰 invisibleAnnotations;且不检查注解是否已存在。

阶段与语义

@ThreadSafeISBRH 的 RetentionPolicy.RUNTIME(见 API 层 对应条目)决定了本 transformer 必须在类被加载后、实例化前完成——也就是 LaunchWrapper 的 IClassTransformer#transform 阶段,正好是 GenericCompatTransformer 所在的位置。RFB 路径不提供本 transformer。

数据提供方(3 个 handler)

Handler 条目数 perThread 取值
ExtraUtils 5 混合:true×2,false×3
ImmersiveEngineering 8 全部 false
StacksOnStacks 1 true

全开时目标类共 14 个。

已知问题

  1. 不幂等:visibleAnnotations.add(...) 无存在性检查。若同一目标类被两个来源打标(例如 handler 数据表重叠,或该类同时被 RFB 与 FML 路径处理),会得到重复注解,而 Java 对重复非 Repeatable 注解的容忍度取决于反射调用方——getAnnotation() 返回第一个,getAnnotations() 返回两个,可能导致不一致。
  2. values 直接赋值 Arrays.asList("perThread", perThread):这是 ASM AnnotationNode.values 的「交替键值」格式,正确。但它写死了元素名 "perThread",若注解未来加第二个成员,构造与读取方会失配(读取方按 values.get(0) 取名)。
  3. 只贴注解、不做校验:perThread=false 意味着主线程实例被所有构建线程共享,api/ThreadSafeISBRH 的 Javadoc 明确警告此类实现「不应存非 final 状态」,但本 transformer 不做任何检查——这是 ImmersiveEngineeringCompatHandler 8 个类全标 false 的风险来源。
  4. 无 Javadoc、无日志:本类完全静默,贴标成功与否无法从日志确认(对比其余 3 个 generic/ transformer 至少有 warn 路径)。

相关条目