fix(compat): load warashi tracker via context classloader

上一版用 ModContainer.getClassLoader() 编译失败(该 API 不存在)。
改为:线程上下文 classloader + Class.forName 默认加载 双重兜底,
均失败则桥降级 no-op。不依赖任何具体 loader API。
This commit is contained in:
Xiao-no-love committed 2026-10-13 15:33:53 +08:00
1 parent cc0cbe1679
commit e358289931
1 file changed
+35 -16
@@ -1,7 +1,6 @@
package dev.modzuozhi.core.compat;
import dev.modzuozhi.ModZuozhi;
import net.neoforged.fml.loading.FMLLoader;
import net.minecraft.resources.ResourceLocation;
import java.lang.invoke.MethodHandle;
@@ -17,11 +16,11 @@ import java.lang.invoke.MethodType;
* <p>
* <b>软依赖</b>:DR 不编译期依赖 warashi。仅在 warashi 加载时,通过 {@link MethodHandle}
* 反射调用其 {@code PerfWorkTracker.enterScope(Object)} / {@code exitScope()}。未加载则全 no-op。
* <p>
* 通过 {@code FMLLoader} 检测(与 {@code DimensionalRipperMixinPlugin} 检测 C2ME 同一模式),
* 不引入运行时类加载风险。
*/
public final class WarashiScopeBridge {
private static final String TRACKER_CLASS =
"com.moepus.serverwarashi.common.modules.performance.sampling.PerfWorkTracker";
private static final MethodHandle ENTER_SCOPE;
private static final MethodHandle EXIT_SCOPE;
private static final boolean ACTIVE;
@@ -31,19 +30,19 @@ public final class WarashiScopeBridge {
MethodHandle exit = null;
boolean active = false;
try {
var loadingMods = FMLLoader.getLoadingModList();
boolean warashiLoaded = loadingMods != null
&& loadingMods.getModFileById("serverwarashi") != null;
boolean warashiLoaded = net.neoforged.fml.ModList.get()
.getModContainerById("serverwarashi").isPresent();
if (warashiLoaded) {
Class<?> tracker = Class.forName(
"com.moepus.serverwarashi.common.modules.performance.sampling.PerfWorkTracker");
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
enter = lookup.findStatic(tracker, "enterScope",
MethodType.methodType(void.class, Object.class));
exit = lookup.findStatic(tracker, "exitScope",
MethodType.methodType(void.class));
active = true;
ModZuozhi.LOGGER.info("[DimThread] ServerWarashi 检测到,已挂接采样作用域桥");
Class<?> tracker = loadTrackerClass();
if (tracker != null) {
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
enter = lookup.findStatic(tracker, "enterScope",
MethodType.methodType(void.class, Object.class));
exit = lookup.findStatic(tracker, "exitScope",
MethodType.methodType(void.class));
active = true;
ModZuozhi.LOGGER.info("[DimThread] ServerWarashi 检测到,已挂接采样作用域桥");
}
}
} catch (Throwable t) {
// warashi 未加载 / 签名不匹配:静默降级为 no-op,绝不影响 DR 主流程。
@@ -60,6 +59,26 @@ public final class WarashiScopeBridge {
private WarashiScopeBridge() {
}
/**
* 加载 warashi 的 {@code PerfWorkTracker} 类。
* <p>
* 依次尝试:线程上下文 classloader(FML 运行期通常是能看全部 mod 的 TransformingClassLoader),
* 以及不带显式 loader 的默认加载。均失败返回 null(桥降级为 no-op)。
*/
private static Class<?> loadTrackerClass() {
try {
return Class.forName(TRACKER_CLASS, false,
Thread.currentThread().getContextClassLoader());
} catch (Throwable ignored) {
// fallthrough
}
try {
return Class.forName(TRACKER_CLASS);
} catch (Throwable ignored) {
return null;
}
}
/** 是否成功挂接 warashi。 */
public static boolean isActive() {
return ACTIVE;