Java 9,ClassLoader.getSystemClassLoader的兼容性问题 [英] Java 9, compatability issue with ClassLoader.getSystemClassLoader

查看:159
本文介绍了Java 9,ClassLoader.getSystemClassLoader的兼容性问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码将jar文件添加到构建路径,它适用于Java 8.但是,它会抛出Java 9的异常,该异常与转换为URLClassLoader有关。有什么想法可以解决这个问题吗?最佳解决方案将对其进行编辑,以便与Java 8和Java 8兼容。 9。

The following code adds jar file to the build path, it works fine with Java 8. However, it throws exception with Java 9, the exception is related to the cast to URLClassLoader. Any ideas how this can be solved? an optimal solution will edit it to work with both Java 8 & 9.

private static int AddtoBuildPath(File f) {
    try {
        URI u = f.toURI();
        URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
        Class<URLClassLoader> urlClass = URLClassLoader.class;
        Method method = urlClass.getDeclaredMethod("addURL", URL.class);
        method.setAccessible(true);
        method.invoke(urlClassLoader, u.toURL());
    } catch (NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException | MalformedURLException | IllegalAccessException ex) {
        return 1;
    }

    return 0;
}


推荐答案

我偶然发现了这个问题不久前。很多,我使用了类似于问题的方法

I have stumbled over this issue a while ago. As many, I had used a method similar to that in the question

private static int AddtoBuildPath(File f)

在运行时动态添加路径到类路径。问题中的代码可能是多方面的坏风格:1)假设ClassLoader.getSystemClassLoader()返回URLClassLoader是一个未记录的实现细节,2)使用反射使addURL公开可能是另一个。

to dynamically add paths to the classpath at runtime. The code in the question is probably bad style in multiple aspects: 1) assuming that ClassLoader.getSystemClassLoader() returns an URLClassLoader is an undocumented implementation detail and 2) using reflection to make addURL public is maybe another one.

动态添加类路径的更清洁方法

如果您需要为类使用其他类路径URL通过 Class.forName 加载,一个干净,优雅和兼容(Java 8到10)的解决方案如下:

In case that you need to use the additional classpath URLs for class loading though „Class.forName", a clean, elegant and compatible (Java 8 to 10) solution is the following:

1)通过扩展URL类加载器编写自己的类加载器,具有公共addURL方法

1) Write your own class loader by extending URL classloader, having a public addURL methods

public class MyClassloader extends URLClassLoader {

    public MyClassloader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
    }

    public void addURL(URL url) {
        super.addURL(url);
    }
}

2)声明一个(单例/ app宽)对象您的类加载器

2) Declare a (singleton/app wide) object of your classloader

private final MyClassloader classLoader;

并通过

classLoader = new MyClassloader(new URL[0], this.getClass().getClassLoader());

注意:系统类加载器是父级。通过 classLoader 加载的类知道那些可以通过 this.getClass()。getClassLoader()加载但不能加载的其他类两种方式。

Note: The system class loader is the parent. Classes loaded though classLoader know those who can be loaded through this.getClass().getClassLoader() but not the other way around.

3)在需要时(动态)添加额外的类路径:

3) Add additional classpaths whenever needed (dynamically):

File file = new File(path);
if(file.exists()) {
    URL url = file.toURI().toURL();
    classLoader.addURL(url);
}

4)通过单件类加载器实现对象或您的应用程序

4) Instanciate objects or your app though your singleton classloader via

cls = Class.forName(name, true, classLoader);

注意:由于类加载器在加载类(和父类)之前尝试委托给父类加载器在父类中,你必须确保要加载的类对父类加载器不可见,以确保通过给定的类加载器加载。

Note: Since class loaders try a delegation to the parent class loader prior loading a class (and the parent to its parent), you have to make sure that the class to load is not visible to the parent class loader to make sure that is loaded through the given class loader.

5)您可以考虑通过

setContextClassLoader(classLoader)

如果线程使用 getContextClassLoader

这篇关于Java 9,ClassLoader.getSystemClassLoader的兼容性问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆