jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to java.net.URLClassLoader

  final URLClassLoader urlClassLoader = (URLClassLoader) MyClass.class.getClassLoader();

            final Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);

            addURL.setAccessible(true);

            addURL.invoke(urlClassLoader, new File(newpath.trim()).toURI().toURL());

在使用Java9之后发的版本汇报如下错误:

Exception in thread "main" java.lang.RuntimeException: java.lang.ClassCastException: jdk.internal.loader.ClassLoaders$AppClassLoader (in module: java.base) cannot be cast to java.net.URLClassLoader (in module: java.base)

Java9之后,应用程序和扩展类都不再是 java.net.URLClassLoader 的实例

因此,解决办法如下:

    if (classLoader instanceof URLClassLoader) {
      System.out.println("DEB: classLoader instanceof URLClassLoader");
      URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
      Class sysclass = URLClassLoader.class;
      try {
        Method method = sysclass.getDeclaredMethod("addURL", URL.class);
        method.setAccessible(true);
        method.invoke(sysloader, url);
      } catch (Exception var5) {
        var5.printStackTrace();
        throw new IllegalStateException(var5.getMessage(), var5);
      }
    } else {
      try {
        Field field = classLoader.getClass().getDeclaredField("ucp");
        field.setAccessible(true);
        Object ucp = field.get(classLoader);

        System.out.println("DEB: invoke method!");
        Method method = ucp.getClass().getDeclaredMethod("addURL", URL.class);
        method.setAccessible(true);

        method.invoke(ucp, url);
      } catch (Exception exception) {
        exception.printStackTrace();
        throw new IllegalStateException(exception.getMessage(), exception);
      }
    }

但是此时仍然会报错:

java.lang.reflect.InaccessibleObjectException: Unable to make field final jdk.internal.loader.URLClassPath jdk.internal.loader.ClassLoaders$AppClassLoader.ucp accessible: module java.base does not "opens jdk.internal.loader" to unnamed module @6b143ee9

因为在 Java 9+ 以上版本中不允许使用动态加载类,因为想要使用就需要加两个参数给虚拟机
此时的解决办法是:

java --add-opens java.base/jdk.internal.loader=ALL-UNNAMED --add-opens jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED -jar  xx.jar

即可

你可能感兴趣的:(编程积累)