5

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

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

  1. 用我的主 jar打包Bar.jar以将其包含在类路径中。这对于插件系统来说显然是不可行的
  2. Foo使用指向 jar 的 URL ClassLoader 加载类。这对于默认的 java 程序员来说太不熟悉了,无法通过其名称手动加载类
  3. 通过参数将自定义类加载器设置为系统类加载器-Djava.system.class.loader。但我真的不想强迫用户使用额外的参数来启动他的应用程序。

还有其他方法吗?也许可以为特定类注册自定义类加载器?或更改new在运行时使用的类加载器?设置 的ContextClassLoader不起作用Thread

4

1 回答 1

8

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

class A {
    B b = new B();

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

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

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

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

于 2013-11-10T17:09:06.547 回答