You need to enable JavaScript to run this app. Java运行时如何从.jmod模块文件加载类
优惠活动
大模型
产品
解决方案
定价
更多

Java运行时如何从.jmod模块文件加载类

首先明确核心原因:.jmod 是JDK9为模块化系统设计的专属归档格式,和普通.jar的标准ZIP结构不兼容,有独立的文件索引、校验规则,这也是URLClassLoader无法直接读取jmod内容的根本原因。

可行实现方案

零内置依赖实现

JDK从9版本开始,运行时自带了专门处理jmod文件的工具类,位于com.sun.tools.jmod包下,不需要引入第三方包即可完成jmod内容解析。
实现逻辑:

  • 用JmodFile类直接打开目标jmod文件,获取内部所有文件条目的遍历能力
  • 自定义类加载器重写findClass方法:根据传入的类名,拼接成jmod内部类文件的标准路径(类名转为斜杠分隔路径,前缀补全classes/),从jmod条目流中读取对应类的字节码,再通过defineClass方法把字节码转换为可被JVM识别的Class对象

核心参考代码:

// 打开目标jmod文件
JmodFile jmodFile = new JmodFile(Paths.get("目标.jmod文件路径"));
// 自定义类加载器
ClassLoader jmodLoader = new ClassLoader(Application.class.getClassLoader()) {
    @Override
    protected Class<?> findClass(String className) throws ClassNotFoundException {
        String entryPath = "classes/" + className.replace('.', '/') + ".class";
        JmodFile.Entry targetEntry = jmodFile.stream()
                .filter(entry -> entry.path().equals(entryPath))
                .findFirst()
                .orElseThrow(() -> new ClassNotFoundException(className));
        byte[] classByteCode = jmodFile.readAllBytes(targetEntry);
        return defineClass(className, classByteCode, 0, classByteCode.length);
    }
};

注意:调用内置jmod工具类时,需要在编译配置中将jdk.jmod模块加入编译路径,否则会出现类找不到的编译错误。

兼容适配方案

如果介意com.sun开头的内部API在不同JDK版本下的兼容差异,可以选用完全独立实现的jmod解析开源库。这类库内置了jmod格式的完整解析逻辑,不依赖JDK非公开接口,跨JDK版本兼容性更稳定。


IDE场景优化提示

做代码内容提示的场景,不需要走完整的类加载流程:

  • 从jmod流中读取类字节码后,可直接用ASM等轻量字节码解析库提取类的结构信息(方法签名、字段、继承关系、注解内容),不需要真的把类加载到JVM内存中完成初始化。相比之前调用javap命令的方案,整体性能会提升数倍
  • 第一次解析完jmod的类结构后,可将索引结果存在本地缓存,IDE下次启动时直接读取缓存内容,不需要重复扫描大体积的jmod文件,进一步降低启动阶段的加载耗时

内容的提问来源于stack exchange,提问作者Omega UI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.27 03:15:04