我正在尝试动态加载库,而不是将它们隐藏到我的 JAR 中以减小文件大小。它是一个独立的应用程序,具有
Boostrap
类和 Main
类。主类负责加载库和调用boostrap类的execute(...)
方法。
使用
Class.forName(class, true, libraryLoader)
下载工件和加载库类是有效的,但是当我尝试加载 Bootstrap
类时,它找不到库类的类定义。
这是我目前正在努力实现这一目标的方法:
/////// Main.java ////////
/* ... public static void main(String[] args) { */
// download libraries
// these URLs reference the local JAR files downloaded
// im not going to get into detail on how im doing this right now, as this works
URL[] libraryUrls = ...;
// create parent loader for libraries
final ClassLoader rootLoader = Main.class.getClassLoader(); // app class loader
ClassLoader libraryLoader = new DelegatingClassLoader(new URLClassLoader(
libraryUrls,
rootLoader
), rootLoader);
/* this passes, so the libraries are successfully loaded onto the loaders ucp */
Class.forName("org.eclipse.jgit.transport.CredentialsProvider", true, libraryLoader);
// find URL for JAR of bootstrap class
ProtectionDomain domain = Main.class.getProtectionDomain();
CodeSource source = domain.getCodeSource();
URL file = source.getLocation();
// create child loader with our JAR file
ClassLoader appLoader = new DelegatingClassLoader(new URLClassLoader(
new URL[] { file }, libraryLoader), libraryLoader);
// load bootstrap class and execute
Class<?> bootstrap = Class.forName( // the error occurs here
"my.package.Bootstrap",
/* initialize */ true,
appLoader
);
bootstrap.getMethod("execute", String[].class)
.invoke(null, (Object) args);
/* } ... */
DelegatingClassLoader
首先尝试通过委托加载一个类,如果失败则委托给父级。 这里是确切的来源。
我得到的具体错误:
Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/jgit/transport/CredentialsProvider
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:467)
at my.package.Main.main(Main.java:108)
// line 108 is the line where i call Class.forName("my.package.Bootstrap, ...)
我期待对库类的引用被正确解析,因为
Bootstrap
类的类加载器应该委托给库类加载器,我确认它已经成功“加载”了库。