如何在运行时向扩展类加载器添加/加载类?

时间:2015-10-15 09:49:02

标签: java classloader

在我的项目中(在运行时): 应用程序类加载器加载了一些类。我有一个用户类加载器,加载了一些类。

现在应用程序类加载器中有一个类正在尝试加载应用程序类加载器中不存在的类,但存在于用户类加载器中。

例如:Application类加载器中的类,其代码类似于

this.getClass().getClassLoader().loadClass("user class").

注意:我没有访问类(在应用程序类加载器中),我无法添加类来加载到应用程序类加载器。

如何加载这样的类?

  

这种情况发生在Drivermanager类中:

     

我在Application Class Loader和Driver类中有DriverManager   用户类加载器。并且DriverManager尝试加载驱动程序类   应用程序类加载器,它无法加载类。

     

所以我想将驱动程序类添加到应用程序或Extension类加载器   在运行时。但是怎么做?

2 个答案:

答案 0 :(得分:3)

尝试使用线程类加载器:

Class<?> driverClass = Thread.currentThread().getContextClassLoader().loadClass("user class name")

在你的例子中:

userDriver = (Driver) driverClass.newInstance();

我认为这些用户类将在Application类加载器中实现一些定义(加载)的接口,因此您将通过此接口处理它们。在这种情况下,使用这样的加载类应该没有问题。

您可以使用默认构造函数从中实例化对象实例(但必须捕获一些异常):

String

如果您想使用其他构造函数(例如,使用Constructor<?> c = driverClass.getConstructor(String.class); userDriver = (Driver) c.newInstance("String param to constructor"); 参数):

def inplace_rotate(l):
  l[:] = l[-1:] + l[0:-1]

答案 1 :(得分:1)

我有两个解决方案,

1)覆盖Driver manager类并使用 Thread.currentThread()。getContextClassLoader()而不是this.getClass()。getClassLoader()来加载驱动程序类。

2)获取System类加载器实例,系统类加载器addURL()中有受保护的api,它在运行时向系统类加载器添加资源。

通过使用反射,如果你可以调用addURL()api,那么驱动程序类将可以在系统类加载器中使用驱动程序管理器。    这是代码sanppit

    URL[] urls = new URL[]{jarFile.toURL()};
    ClassLoader cl = ClassLoader.getSystemClassLoader()
    if ( cl instanceof URLClassLoader ) {
        URLClassLoader ul = (URLClassLoader) cl;

        // addURL is a protected method, but we can use reflection to call it
        Class<?>[] paraTypes = new Class[1];
        paraTypes[0] = URL.class;
        Method method = URLClassLoader.class.getDeclaredMethod("addURL", paraTypes);
        method.setAccessible(true);
        Object[] args = new Object[1];
        for (int i = 0; i < urls.length; i++) {
            args[0] = urls[i];
            method.invoke(ul, args);
        }
    }

注意:这样,您只能将资源添加到系统类加载器,但是您无法从类加载器中注销添加的资源。如果您有版本的jar,则会导致结果出现。