如何在 modulairzed java 11 应用程序中动态加载 Libreoffice jar 而无需从自定义 class 加载器获取 ClassCastException
How to load Libreoffice jars dynamically in modulairzed java 11 application without getting a ClassCastException from custom class loader
我正尝试在 运行 时间从模块化 java 11 应用程序加载和访问 libreoffice uno jar。
为了在编译时使用 libreoffice classes 并避免拆分包出现问题,我们将所有 jar 合并到一个 single one 中,并使用自动模块名称 org.jabref.thirdparty.libreoffice
。
从 libreoffice 安装目录加载 jar(例如 C:\Program Files\LibreOffice\program\classes
为了确保从程序文件而不是我的模块路径加载 jar,我创建了一个自定义类加载器。
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 文件夹中的 jars,否则它将找不到 libreoffice 实例。我也考虑过将模块化的 jar 放入 LO 文件夹中,但不确定是否可行。
在 Java 8 下,我们使用了典型的 "reflection + addUrls" 方法,因为所有内容都在 class 路径上。
这是定制的 class 老兄:
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;
}
}
从 LibreOffice 7.0 开始,现在有一个与 Java 模块系统一起工作的组合 libreoffice.jar。
我正尝试在 运行 时间从模块化 java 11 应用程序加载和访问 libreoffice uno jar。
为了在编译时使用 libreoffice classes 并避免拆分包出现问题,我们将所有 jar 合并到一个 single one 中,并使用自动模块名称 org.jabref.thirdparty.libreoffice
。
从 libreoffice 安装目录加载 jar(例如 C:\Program Files\LibreOffice\program\classes
为了确保从程序文件而不是我的模块路径加载 jar,我创建了一个自定义类加载器。
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 文件夹中的 jars,否则它将找不到 libreoffice 实例。我也考虑过将模块化的 jar 放入 LO 文件夹中,但不确定是否可行。
在 Java 8 下,我们使用了典型的 "reflection + addUrls" 方法,因为所有内容都在 class 路径上。
这是定制的 class 老兄:
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;
}
}
从 LibreOffice 7.0 开始,现在有一个与 Java 模块系统一起工作的组合 libreoffice.jar。