Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which ClassLoader should I supply to Proxy.newProxyInstance(...)?

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.

like image 316
jonderry Avatar asked Mar 29 '11 23:03

jonderry


1 Answers

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 :-)

like image 97
Paŭlo Ebermann Avatar answered Oct 22 '22 20:10

Paŭlo Ebermann