LoaderUtil 路径缓存

基本信息

属性 值
类 com.mitchej123.jarjar.fml.common.LoaderUtil
静态缓存 ConcurrentMap<Path, Path> pathNormalizationCache

LoaderUtil 提供 Path 归一化(realpath)缓存。path.toRealPath() 是 fs syscall(FOLLOW_LINK + resolve symlink + normalize),同一 Path 在 Mod 发现阶段会被多次访问,缓存避免重复 IO。

方法

public static String getClassFileName(String className) {
    return className.replace('.', '/').concat(".class.class");
}

public static Path normalizePath(Path path) {
    if (Files.exists(path)) return normalizeExistingPath(path);
    else return path.toAbsolutePath().normalize();
}

public static Path normalizeExistingPath(Path path) {
    return pathNormalizationCache.computeIfAbsent(path, LoaderUtil::normalizeExistingPath0);
}

private static Path normalizeExistingPath0(Path path) {
    try {
        return path.toRealPath();
    } catch (IOException e) {
        throw new UncheckedIOException(e);
    }
}

使用点

  • DirectoryModCandidateFinder 构造函数:LoaderUtil.normalizePath(path)
  • ParallellModDiscoverer.discoverMods 内的 processedPaths.add(path) 前:path.equals(LoaderUtil.normalizeExistingPath(path)) —— assert 保证入队 path 已经 realpath
  • DirectoryModCandidateFinder.findCandidates 额外 mod:LoaderUtil.normalizePath(additionalMod.toPath())

缓存命中

Path p1 = Paths.get("/home/evlos/mods/gregtech.jar");
Path p2 = Paths.get("/home/evlos/mods/gregtech.jar");   // 实际可能是符号链接解析后
normalizeExistingPath(p1);   // 触发 syscall + 缓存
normalizeExistingPath(p2);   // 缓存命中

ConcurrentHashMap.computeIfAbsent 线程安全,多 finder 并发时无锁竞争。

相关条目