You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openwebbeans.apache.org by Mark Struberg <st...@yahoo.de> on 2013/01/22 12:33:24 UTC

The pittfalls of ClassLoaders for proxies

Hi folks!

A small culprit I found in our proxy code yesterday night:

Consider the following (the 'protected' is important!)

public class User {
  protected String getName() { return "Hans";}
}

User$Proxy extends User
   private User delegate;

  protected String getName {
    return delegate.getName();
  }
}


This code works perfect! But only as long as the User$Proxy and User classes are loaded with the same ClassLoader. According to the JVM 2 classes are only considered to be in the same package (and thus allows for protected access) if they are loaded by the same ClassLoader.
This is what caused problems in Javassist as well, and there we had to do some weird hacks with the ClassLoaderProvider factory. 

The solution I did now is the following: I use the ClassLoader of the original class to define the Proxy. This works perfectly fine, but only as long as we don't proxy classes which are not meant to be 'shared'.  Imagine a full-profile EE server where you have e.g. MyFaces in the servers lib folder, which would result in a ClassLoader hierarchy similar to:

SystemClassLoader 
 -> EE-server-internal (contains myfaces-*.jar)
    -> EE-server-lib
      -> EAR-A ->warA1, warA2, etc
      -> EAR-B ->warB1, warB2, etc

But any proxies for e.g. javax.faces.context.FacesContext should not be loaded with the EE-server-internal ClassLoader but maximum with EAR-A or EAR-B ClassLoaders. 


This means we should introduce an upper boundary ClassLoader detection somehow. We might need the same for the HierarchicScannerService as well btw.

I already added a detection if proxyClassLoader != proxiedClassClassLoader and in that case I skip the proxying of protected methods. We might also automatically switch to using reflection in that case, but this is imo not required by the specs.

Any objections? Any ideas?


LieGrue,
strub

Re: The pittfalls of ClassLoaders for proxies

Posted by Joseph Bergmark <be...@apache.org>.
Sorry for the late response, but I don't think you have to worry about
the hierarchical class loader scenario you described below.

At least in the server I'm aware of, the modules classloaders all
delegate up to the shared classloader.  If they didn't then each
module classloader would be loading a unique copy of that class, which
would defeat the purpose of having a shared library in the first
place.

Sincerely,

Joe

On Tue, Jan 22, 2013 at 6:33 AM, Mark Struberg <st...@yahoo.de> wrote:
> Hi folks!
>
> A small culprit I found in our proxy code yesterday night:
>
> Consider the following (the 'protected' is important!)
>
> public class User {
>   protected String getName() { return "Hans";}
> }
>
> User$Proxy extends User
>    private User delegate;
>
>   protected String getName {
>     return delegate.getName();
>   }
> }
>
>
> This code works perfect! But only as long as the User$Proxy and User classes are loaded with the same ClassLoader. According to the JVM 2 classes are only considered to be in the same package (and thus allows for protected access) if they are loaded by the same ClassLoader.
> This is what caused problems in Javassist as well, and there we had to do some weird hacks with the ClassLoaderProvider factory.
>
> The solution I did now is the following: I use the ClassLoader of the original class to define the Proxy. This works perfectly fine, but only as long as we don't proxy classes which are not meant to be 'shared'.  Imagine a full-profile EE server where you have e.g. MyFaces in the servers lib folder, which would result in a ClassLoader hierarchy similar to:
>
> SystemClassLoader
>  -> EE-server-internal (contains myfaces-*.jar)
>     -> EE-server-lib
>       -> EAR-A ->warA1, warA2, etc
>       -> EAR-B ->warB1, warB2, etc
>
> But any proxies for e.g. javax.faces.context.FacesContext should not be loaded with the EE-server-internal ClassLoader but maximum with EAR-A or EAR-B ClassLoaders.
>
>
> This means we should introduce an upper boundary ClassLoader detection somehow. We might need the same for the HierarchicScannerService as well btw.
>
> I already added a detection if proxyClassLoader != proxiedClassClassLoader and in that case I skip the proxying of protected methods. We might also automatically switch to using reflection in that case, but this is imo not required by the specs.
>
> Any objections? Any ideas?
>
>
> LieGrue,
> strub