Java 我应该向Proxy.newProxyInstance(…)提供哪个类加载器?

Java 我应该向Proxy.newProxyInstance(…)提供哪个类加载器?,java,reflection,classloader,Java,Reflection,Classloader,我已经阅读了文档,但仍然不明白应该提供哪个类加载器作为参数。我尝试了一些选项,但这似乎对编译或代理的行为没有影响。有点令人不安的是,我可以将任何内容作为类加载器参数传递,包括null,并且代码仍然可以正常工作。有人能解释一下吗?如果我为类加载器提供了一个错误的参数,会出现什么样的错误?我应该补充一点,在Java或一般情况下,我对什么是类加载器没有很强的直观概念。任何类都需要有类加载器,因此我们必须在这里给出一个类加载器 重要的部分是: 所有接口类型必须通过指定的类加载器按名称可见。换句话说,,

我已经阅读了文档,但仍然不明白应该提供哪个类加载器作为参数。我尝试了一些选项,但这似乎对编译或代理的行为没有影响。有点令人不安的是,我可以将任何内容作为类加载器参数传递,包括
null
,并且代码仍然可以正常工作。有人能解释一下吗?如果我为类加载器提供了一个错误的参数,会出现什么样的错误?我应该补充一点,在Java或一般情况下,我对什么是类加载器没有很强的直观概念。

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

重要的部分是:

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

Class.forName(i.getName(), false, cl) == i
因此,您可以在一个(或多个)父类加载器定义给定接口的情况下使用任何类加载器

如果
null
在您的情况下起作用,我假设您的接口也有
null
类加载器(引导加载器)-那么使用哪个类加载器应该无关紧要。如果您必须从您不知道的接口创建代理,只需使用给定的第一个接口的类加载器,并希望您的调用者没有做任何奇怪的事情

为什么需要它?

你可以这样想象:

  • getProxyClass()
    方法为实现所有接口的所有方法的新类创建(如果它还不存在的话)一些字节码(每个方法都只是将调用转发给
    InvocationHandler
  • 然后它将这个字节码传递给您指定的类加载器的
    defineClass
    方法
  • 在这个字节码中,所有接口都由名称引用,VM现在使用引用的
    forName
    调用来解析这些接口
我们本可以在纯Java中以这种方式实现这个
getProxyClass
,而不需要任何VM魔法,但是我们需要为它创建一个新的类加载器(将指定的类加载器作为父类),而不是能够重用现有的类加载器


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

谢谢,我仍然没有类加载器的直觉。你能谈谈这件事吗?我仍然很难理解,如果类加载器负责做任何实质性的事情,为什么空类加载器可以工作。可能是一个玩具示例,其中给出了一个错误的类加载器。
null
类加载器是“引导类加载器”,加载核心类的类加载器(如
Class
Object
classloader
)。它由VM本机实现,没有ClassLoader对象。(例如,如果将
null
作为
ClassLoader
参数,则
Class.forName
将使用它)。(稍后会有一个例子。)@PaŭloEbermann只是为了确认我理解正确,
任何类加载器,其中一个(或多个)父类加载器定义了给定的接口
,基本上是指加载接口的确切类加载器,以及该接口的任何祖先加载器。是否正确?@wlnirvana如果您使用了
Class iface=cl.loadClass(…)
,那么您可以使用相同的
cl
(它将是定义类加载器的后代)作为newProxyInstance的参数。或者您可以只使用
接口.class.getClassLoader()
,这将是定义类加载器本身。