如何在模块化的 java 11 应用程序中动态加载 Libreoffice jar,而不从自定义类加载器中获取 ClassCastException

Posted

技术标签:

【中文标题】如何在模块化的 java 11 应用程序中动态加载 Libreoffice jar,而不从自定义类加载器中获取 ClassCastException【英文标题】:How to load Libreoffice jars dynamically in modulairzed java 11 application without getting a ClassCastException from custom class loader 【发布时间】:2019-09-08 18:00:03 【问题描述】:

我正在尝试在运行时从模块化 java 11 应用程序加载和访问 libreoffice uno jar。

为了在编译时使用 libreoffice 类并避免拆分包的问题,​​我们将所有 jar 合并到一个 single one 中,自动模块名称为 org.jabref.thirdparty.libreoffice

为了从 libreoffice 安装目录加载 jars(例如C:\Program Files\LibreOffice\program\classes 为了确保从程序文件而不是从我的模块路径加载 jars,我创建了一个自定义类加载器。

   URL[] urls = jarUrls.toArray(new URL[3]);
    Class<Bootstrap> clazz  = (Class<Bootstrap>) Class.forName("com.sun.star.comp.helper.Bootstrap", true, new ChildFirstClassLoader(urls, this.getClass().getClassLoader()));
    Boostrap boot = clazz.getDeclaredConstructor().newInstance();
    XComponentContext xContext = boot.bootstrap():

现在这给了我以下错误:

 java.lang.ClassCastException: class com.sun.star.comp.helper.Bootstrap cannot be cast to class com.sun.star.comp.helper.Bootstrap (com.sun.star.comp.helper.Bootstrap is in unnamed module of loader org.jabref.logic.openoffice.ChildFirstClassLoader @13c4b54c; com.sun.star.comp.helper.Bootstrap is in module org.jabref.thirdparty.libreoffice of loader 'app')

我确实了解这里的问题并阅读了很多关于此的内容,但找不到解决此问题的方法。关键问题是我必须使用 LO 文件夹中的 jar,否则它将找不到 libreoffice 实例。我也想过将模块化的 jar 放入 LO 文件夹中,但不确定这是否可行。

在 Java 8 下,我们使用典型的“反射 + addUrls”方法,因为所有内容都在类路径中。

这是自定义类加载器:

public class ChildFirstClassLoader extends URLClassLoader 

    public ChildFirstClassLoader(URL[] urls, ClassLoader parent) 
        super(urls, parent);
    

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException 
        // has the class loaded already?
        Class<?> loadedClass = findLoadedClass(name);
        if (loadedClass == null) 
            try 
                // find the class from given jar urls 
                loadedClass = findClass(name);
             catch (ClassNotFoundException e) 
                // Hmmm... class does not exist in the given urls.
                // Let's try finding it in our parent classloader.
                // this'll throw ClassNotFoundException in failure.                  
                loadedClass = super.loadClass(name, resolve);
            
        
        if (resolve)  // marked to resolve
            resolveClass(loadedClass);
        
        return loadedClass;
    

【问题讨论】:

【参考方案1】:

从 LibreOffice 7.0 开始,现在有一个与 Java 模块系统一起使用的组合 libreoffice.jar。

【讨论】:

以上是关于如何在模块化的 java 11 应用程序中动态加载 Libreoffice jar,而不从自定义类加载器中获取 ClassCastException的主要内容,如果未能解决你的问题,请参考以下文章

如何在 react-native 中动态加载模块?

每个模块的菜单项,模块内容使用 Prism 或 MEF 动态加载

NGINX 加载动态模块(NGINX 1.9.11开始增加加载动态模块支持)

动态加载模块,python反射机制

在 Elixir 或 Erlang 中,如何在运行时动态创建和加载模块?

在 C 中创建模块系统(动态加载)