1.8 如何在运行时动态加载JAR文件? | Java Debug 笔记

310 阅读1分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看<活动链接>

提问:如何在运行时动态加载JAR文件?

为什么用Java实现这个需求这么难?如果要使用任何类型的模块系统,则需要能够动态加载JAR文件。有人告诉我,有一种方法可以通过编写自己的ClassLoader方法来完成。但这是大量的工作,而我期待他可以像加个参数一样那么简单。

回答1:

很难的原因是安全性。类加载器是不可变的。您不应在运行时随意向其添加类。实际上,我很惊讶系统类加载器能被如此用。这是制作自己的子类加载器的方法:

URLClassLoader child = new URLClassLoader(
        new URL[] {myJar.toURI().toURL()},
        this.getClass().getClassLoader()
);
Class classToLoad = Class.forName("com.MyClass", true, child);
Method method = classToLoad.getDeclaredMethod("myMethod");
Object instance = classToLoad.newInstance();
Object result = method.invoke(instance);

回答2:

以下解决方案有些骇人听闻,因为它使用反射来绕过封装,但是可以完美地工作:

File file = ...
URL url = file.toURI().toURL();

URLClassLoader classLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
method.invoke(classLoader, url);

回答3: JCL类加载器的框架怎么样?我不得不承认,我没有使用过,但是看起来很有希望。

用法示例:

JarClassLoader jcl = new JarClassLoader();
jcl.add("myjar.jar"); // Load jar file  
jcl.add(new URL("http://myserver.com/myjar.jar")); // Load jar from a URL
jcl.add(new FileInputStream("myotherjar.jar")); // Load jar file from stream
jcl.add("myclassfolder/"); // Load class folder  
jcl.add("myjarlib/"); // Recursively load all jar files in the folder/sub-folder(s)

JclObjectFactory factory = JclObjectFactory.getInstance();
// Create object of loaded class  
Object obj = factory.create(jcl, "mypackage.MyClass");