Springboot 使用 JavaCompiler 时报错 ClassNotFoundException

首先要指定 classpath,有多个值时要用分隔符分割开。在 Windows 上分隔符是英文分号,在 Linux 上是英文冒号。下面是示例代码:

String osName = System.getProperty("os.name").toLowerCase();
String split = osName.startsWith("windows") ? ";" : ":";

List options = new ArrayList<>();
options.add("-classpath");
options.add(path1 + split + path2);

注意 path 的顺序。

编译通过之后使用 URLClassLoader 加载类,这时候还有可能报错 ClassNotFoundException。我遇到的情况是编译的时候依赖包 A 中的 class B,jar 包中也依赖包 A 中的 class B,结果运行的时候说包 A 中的 class B 不存在(ClassNotFoundException)。解决方案是创建 URLClassLoader 对象时指定 parent 参数。下面是示例代码:

import org.springframework.util.ClassUtils;

...

// file:// 必须是双斜线,单斜线在 Linux 上会导致 ClassNotFoundException
URL[] urls = new URL[]{new URL("file://" + path)};
try (URLClassLoader classLoader = new URLClassLoader(urls, ClassUtils.getDefaultClassLoader())) {

...

}

有几点需要注意:

  1. 新建 URL 对象的时候,path 前缀的 file:// 必须是双斜线,单斜线在 Linux 上会导致 ClassNotFoundException,在 Windows 上没有问题
  2. try-with-resource 会自动关闭资源,如果之后还会用到 URLClassLoader 加载的 class,那么不要使用 try-with-resource,将关闭动作放到程序结束时。
  3. 如果需要重新加载某个类,则新建类加载器。因为 Java 类加载器不支持重新加载类,如果想重新加载,那就新建一个类加载器。示例代码和参考文章如下:
    import org.springframework.util.ClassUtils;
    
    ...
    
    // file:// 必须是双斜线,单斜线在 Linux 上会导致 ClassNotFoundException
    URL[] urls = new URL[]{new URL("file://" + path)};
    URLClassLoader classLoader = new URLClassLoader(urls, ClassUtils.getDefaultClassLoader());
    
    ...
    

    java重新加载类_java重新加载类的探寻icon-default.png?t=M4ADhttps://blog.csdn.net/weixin_34664586/article/details/114428479

具体原因不太清楚,哪位大佬明白的话还请解答一下,谢谢!

你可能感兴趣的:(Web,java,开发语言,spring,boot,URLClassLoader)