什么类加载器“新”使用,我如何更改它?

时间:2013-11-10 17:05:46

标签: java classloader

我正在开发一个简单的插件系统,我基本上想控制哪个类加载器在new指令上加载一个类。 例如,我的主程序有一个jar,我在一个名为Foo.class的额外打包jar中分发了一个类Bar.jar

我看到在我的主程序中包含jar的三种不同的可能性:

  1. 使用我的主jar包Bar.jar将其包含在类路径中。对于插件系统来说,这显然是不可行的
  2. 使用指向jar的URL ClassLoader加载类Foo。这对于默认的java程序员来说太熟悉了,无法通过名称
  3. 手动加载类
  4. 通过-Djava.system.class.loader参数将自定义类加载器设置为系统类加载器。但我真的不想强迫用户使用额外的参数启动他的应用程序。
  5. 还有其他方法吗?也许是为特定类注册Custom类加载器的东西?或更改运行时的类加载器new使用?设置ContextClassLoader的{​​{1}}不起作用。

1 个答案:

答案 0 :(得分:7)

当你加载一个类时,它引用的类使用与它相同的类加载器。这意味着要隐式控制使用的类加载器,您可以使用不同的类加载器来启动它。例如你的第一个Runnable。

class A {
    B b = new B();

new B将选择用于A(或父级)的ClassLoader

设置上下文类加载器适用于Class.forName(name);之类的动态查找与Class.forName(Thread.currentThread().getContextClassLoader(), name);

相同

加载一个类后,它将始终使用它所依赖的相同类。根据线程上下文说,不可能交换不同的类。这意味着具有非常特定的类加载器的类可以使用更常用的类(例如,通用类来自父类),但是更通用的类不能使用它不知道的更具体的类加载器。即ClassLoaders不知道他们的孩子。

这样做的一个原因是线程共享内存。这意味着你不能说当A在一个线程中创建一个新B时,它将与另一个线程不同,因为任何一个线程都可以访问A实例。