Java 9运行时动态添加Jar遇ClassNotFoundException,求排查解决
解决Java 9中URLClassLoader类加载问题及ClassNotFoundException的原因
嘿,我来帮你拆解下问题——你碰到的ClassNotFoundException其实是对Class.forName()的用法出现了偏差,咱们一步步理清楚:
核心错误:Class.forName()的参数用错了
Class.forName()的第一个参数要求是类的全限定名(比如com.mycompany.MyNodeClass),但你传的是JAR文件的URL路径字符串,这根本不是一个合法的类名,JVM自然找不到对应的类,直接抛出异常了。
为什么原来的代码在Java 9失效?
Java 9引入了模块化系统(JPMS),对类加载器的访问做了严格限制:URLClassLoader的addNewURL原本就是非公开的内部API,Java 9开始彻底封闭了这类反射修改系统类加载器的操作,这也是你必须替换原有实现的核心原因。
正确的实现方式
咱们的目标是加载指定JAR中的类,正确的步骤应该是:
- 创建自定义的
URLClassLoader,把目标JAR的URL作为加载路径 - 使用这个自定义类加载器,通过类的全限定名来加载具体的类
下面是修正后的代码示例:
import java.net.URL; import java.net.URLClassLoader; import java.lang.reflect.InvocationTargetException; public class MyClass { public static void loadJarClass() throws Exception { // 目标JAR的URL URL jarUrl = new URL("file:/C:/Users/SomeUser/Projects/MyTool/plugins/myNodes/myOwn-nodes-1.6.jar"); // 创建自定义URLClassLoader,父类加载器使用当前类的加载器(保持类加载层次) URLClassLoader customLoader = URLClassLoader.newInstance( new URL[]{jarUrl}, MyClass.class.getClassLoader() ); try { // 替换成你实际要加载的类的全限定名,比如JAR里的com.myplugin.nodes.MyOwnNode Class<?> targetClass = Class.forName("com.myplugin.nodes.MyOwnNode", true, customLoader); // 实例化类(如果需要的话) Object instance = targetClass.getDeclaredConstructor().newInstance(); // 后续可以调用类的方法等操作 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); } finally { // Java 9+中URLClassLoader实现了AutoCloseable,记得关闭资源 customLoader.close(); } } }
额外注意事项
- 如果你要加载的是模块化JAR(包含
module-info.class),需要确保目标模块已经导出了要加载的类,或者通过--add-modules、--add-exports等JVM参数开放访问权限 - Java 9之后系统类加载器已经不再是
URLClassLoader的实例,这也是原有代码中强制类型转换会报错的原因之一,所以尽量避免依赖系统类加载器 - 一定要确认你要加载的类的全限定名完全正确,包括包名,比如JAR中如果有
myOwn.nodes.MyNode类,就要完整传入myOwn.nodes.MyNode
内容的提问来源于stack exchange,提问作者RuntimeError
相关产品推荐
相关产品推荐

