我应该向Proxy.newProxyInstance(...)提供哪种ClassLoader?

jon*_*rry 10 java reflection classloader

我已经阅读了文档,但我仍然不明白我应该提供哪个类加载器作为参数.我尝试了一些选项,但这似乎对编译或代理行为没有影响.我可以将任何东西作为类加载器参数传递,包括null,并且代码仍然可以正常工作,这有点令人不安.任何人都可以解释这一点,并告诉我如果我为类加载器提供一个错误的参数会出现什么样的错误?我应该补充一点,我对Java或一般的类加载器没有一个非常直观的想法.

Paŭ*_*ann 6

任何类都需要一个类加载器,因此我们必须在这里给一个.

重要的是这个(在文档中getProxyClass()):

所有接口类型必须通过指定的类加载器按名称可见.换句话说,对于类加载器cl和每个接口i,以下表达式必须为true:

Class.forName(i.getName(), false, cl) == i
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用其中一个(或多个)父类加载器定义给定接口的任何类加载器.

如果null在你的情况下工作,我想你的接口也有null类加载器(引导加载器) - 那么你使用哪个类加载器并不重要.如果你必须从你不知道的接口创建一个代理,只需要给出第一个接口的类加载器,并希望你的调用者不会做一些奇怪的事情.

为什么需要它?

你可以想象它是这样的:

  • getProxyClass()方法创建(如果它还不存在)一些字节码,用于实现所有接口的所有方法的新类(每个方法只是将调用转发给您InvocationHandler).
  • 然后它将此字节码传递给defineClass您指定的类加载器的方法.
  • 在此字节码中,所有接口都按名称引用,VM现在使用引用的forName调用来解析这些接口.

我们可以getProxyClass在纯Java中以这种方式实现这一点而不需要任何VM魔术,但是我们需要为它创建一个新的类加载器(使用指定的一个作为父类),而不是能够重用现有的类加载器.

实际上,这个合成类可能没有实际的字节码,因为VM可以在这里使用它的内部魔法:-)