【问题标题】:How to load a class from module(.jmod) file at runtime?如何在运行时从模块(.jmod)文件加载类?
【发布时间】:2021-07-02 08:31:48
【问题描述】:

我想在运行时将模块 (.jmod) 文件中的类加载到应用程序内存中。

我知道我们可以使用 :-) 轻松地从 (.jar) 文件中加载类

ClassLoader loader = URLClassLoader.newInstance(new URL[]{
                jarFile.toURL()
            });

总代码sn-p可以在src omega.deassembler.JarLoader类中的this-repo找到

但问题是 URLClassLoader 无法读取模块(.jmod)。

那么是否有任何其他内部类或库可以从模块(.jmod)文件加载类。

实际上,我正在创建一个 IDE,this-repo 是其中的一部分,用于加载内容辅助提示。

之前,我使用 javap 命令来反汇编和加载提示(参见omegaide on github)。

但是这个技巧很费时间,所以我再写一遍!

谢谢。

【问题讨论】:

    标签: java ide classloader javap


    【解决方案1】:

    这并不完全是答案,而是一种使URLClassLoader 在必须读取模块时可用的方法。

    早期的 URLClassLoader 在尝试读取模块文件 (.jmod) 时抛出此异常

    省略模块信息时

    Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/javafx/event/DirectEvent (wrong name: classes/com/sun/javafx/event/DirectEvent)
        at java.base/java.lang.ClassLoader.defineClass1(Native Method)
        at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1010)
        etc
    

    包括元信息

    Exception in thread "main" java.lang.NoClassDefFoundError: classes/module-info is not a class because access_flag ACC_MODULE is set
    
    

    这意味着它无法识别jmod文件中的目录系统

    所以我们知道,一个简单的 jar 文件只包含类和资源(仅排除元信息)。

    在一个模块文件(.jmod)中,所有的类都放在classes文件夹中,所有资源都放在resources文件夹中。

    因此,我们可以创建一个 临时 jar 文件,例如“modular-jar.jar”,其中包含模块文件中的类和资源的内容,

    然后使用标准的 URLClassLoader 我们可以将它加载到类路径中

    然后可以立即删除文件

    这至少在我的情况下有效

    这里是代码sn-p

    public static synchronized JarLoader prepareModule(String modulePath){
            try{
                ZipFile moduleFile = new ZipFile(modulePath);
                ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream("readable-module-data.jar"));
                for(Enumeration enums = moduleFile.entries(); enums.hasMoreElements();){
                    ZipEntry entry = (ZipEntry)enums.nextElement();
                    String name = entry.getName();
                    if((name.startsWith("classes") && !name.contains("module-info")) || name.startsWith("resources")){
                             zipOutputStream.putNextEntry(new ZipEntry(name.substring(name.indexOf('/') + 1)));
                             InputStream in = moduleFile.getInputStream(entry);
                             while(in.available() > 0)
                                  zipOutputStream.write(in.read());
                             zipOutputStream.flush();
                    }
                }
                  zipOutputStream.close();
            }
            catch(Exception e){
                e.printStackTrace();
            }
            return new JarLoader("readable-module-data.jar");
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-18
      • 2019-12-19
      • 2012-06-16
      • 1970-01-01
      • 1970-01-01
      • 2011-02-20
      • 2023-03-10
      • 2023-01-31
      相关资源
      最近更新 更多