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

发布于 2024-10-27 12:51:31 字数 210 浏览 0 评论 0原文

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

I have read the documentation, but I still don't understand which classloader I should supply as an argument. I've tried a few options, but this seems to have no effect on compilation or the behavior of the proxy. It is a little unsettling that I can pass anything as the class loader argument, including null, and the code still works fine. Can anyone explain this, and tell me what kind of errors can arise if I provide a bad argument for the classloader? I should add that I don't really have a strong intuitive idea of what a classloader is, in Java or in general.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

合约呢 2024-11-03 12:51:31

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

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

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

Class.forName(i.getName(), false, cl) == i

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

如果 null 适用于您的情况,我想您的接口也有 null 类加载器(引导加载器) - 那么您使用哪个类加载器应该不重要。如果您必须从您不知道的接口创建代理,只需获取给定的第一个接口的类加载器,并希望您的调用者没有做一些奇怪的事情。

为什么需要它?

你可以这样想象:

  • getProxyClass()方法为实现所有方法的新类创建(如果尚不存在)一些字节码您的所有接口(每个接口都只是将调用转发到您的 InitationHandler)。
  • 然后,它将此字节码传递给您指定的类加载器的 defineClass 方法。
  • 在此字节码中,所有接口均按名称引用,并且虚拟机现在使用引用的 forName 调用来解析这些接口。

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

实际上,这个合成类可能没有实际的字节码,因为虚拟机能够在这里使用其内部魔法:-)

Any class needs to have a classloader, thus we have to give one here.

The important part is this (in the documentation for getProxyClass()):

All of the interface types must be visible by name through the specified class loader. In other words,
for class loader cl and every interface i, the following expression must be true:

Class.forName(i.getName(), false, cl) == i

So, you can use any classloader where one (or more) of its parent classloaders defined the given interfaces.

If null works in your case, I suppose your interfaces have also the null class loader (the bootstrap loader) - then it should not matter which classloader you used. If you have to create an proxy from interfaces you don't know, simply take the classloader of the first interface given and hope your caller did not do something strange.

Why it is needed?

You can imagine it like this:

  • The getProxyClass() method creates (if it does not exist yet) some bytecode for a new class implementing all the methods of all your interface (each of them simply forwarding the call to your InvocationHandler).
  • It then passes this bytecode to the defineClass method of the classloader you specified.
  • In this bytecode, all of your interfaces are referenced by name, and the VM now uses the cited forName call to resolve these interfaces.

We could have implemented this getProxyClass this way in pure Java without any VM magic, but we would need to create a new classloader (with the specified one as a parent) for it instead of being able to reuse an existing one.

In reality there might not be an actual bytecode for this synthetic class, since the VM is able to use its internal magic here :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文