You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@river.apache.org by Peter Firmstone <ji...@zeus.net.au> on 2012/08/11 15:07:30 UTC

CodebaseAccessClassLoader replacement for RMIClassLoader

Just thought I'd get a little clarification on how 
CodebaseAccessClassLoader should work and whether it needs any further 
refinements or tweaks.  I'm currently patching CodebaseAccessClassLoader 
back into the main trunk, so it can make the next release.

All references to RMIClassLoader static method calls (except for 
RMIClassLoader.getDefaultProviderInstance()) in the platform and 
supporting service implementations were replaced with equivalent method 
calls to CodebaseAccessClassLoader, I'm now going through the test kits, 
replacing all similar method calls.

The relationship between PreferredClassProvider, RMIClassLoader and 
CodebaseAccessClassLoader appear circular, so I'm finding it a little 
confusing how it should be applied in Netbeans or an OSGi environment.

Observations:

   1. CodebaseAccessClassLoader is the replacement for RMIClassLoader,
      it has identical static methods (except for
      getDefaultProviderInstance()) and three additional methods
      (identical to CodebaseClassAccess).
   2. CodebaseAccessClassLoader providers must implement the
      CodebaseClassAccess interface, which it delegates to.
   3. CodebaseAccessClassLoader has a static method to change the
      provider, guarded with a security check.
   4. CodebaseClassAccess has identical methods to RMIClassLoader
      (except for getDefaultProviderInstance()) and three additional
      methods:
         1. createClassLoader(URL[] urls, ClassLoader parentLoader,
            boolean requiredDlperm, AccessControlContext ctx)
         2. getParentContextClassLoader()
         3. getSystemContextLoader(ClassLoader defaultLoader).
   5. RMIClassLoaderCodebaseAccess is a wrapper around RMIClassLoader
      that implements CodebaseClassAccess
   6. RMIClassLoaderCodebaseAccess is the default provider for
      CodebaseAccessClassLoader
   7. PreferredClassProvider doesn't implement CodebaseClassAccess.
   8. PreferredClassProvider now calls CodebaseAccessClassLoader to get
      the context ClassLoader (which may now be something other than the
      call Thread's context ClassLoader) and also calls
      CodebaseAccessClassLoader.createClassLoader instead of creating a
      PreferredClassLoader directly.
   9. Call path CodebaseAccessClassLoader -->
      RMIClassLoaderCodebaseAccess --> RMIClassLoader -->
      PreferredClassProvider --> CodebaseAccessClassLoader -->
      RMIClassLoaderCodebaseAccess
  10. The interface CodebaseClassAccess includes deprecated methods from
      RMIClassLoader

A flaw with the original RMIClassLoaderSPI mechanism is you don't get a 
choice of provider, like you do for encryption or other providers, you 
get the first loaded provider.  The ServiceProvider mechanism in Java 6 
is more flexible than RMIClassLoaderSPI, allowing loading from child 
ClassLoaders, not just the system loader.

I understand and appreciate that Gregg has created this to allow 
development using Netbeans, a task which the code has proven successful, 
I also understand that Chris used it with OSGi.  Lets make sure we get 
it right prior to release.


Some Questions:

Should CodebaseAccessClassLoader be used to replace RMIClassLoaderSPI?

Shouldn't PreferredClassProvider also implement CodebaseClassAccess?  So 
it can be used directly as a provider without using RMIClassLoader or 
RMIClassLoaderCodebaseAccess?

Shouldn't PreferredClassProvider provide its own methods for creating 
ClassLoaders and finding the parent ClassLoader rather than relying on 
CodebaseAccessClassLoader, which might be delegating to a different 
provider.

Should we drop the deprecated RMIClassLoader methods?

Should we have additional mechanisms for loading 
CodebaseAccessClassLoader providers other than the static setter 
method?  Eg configuration or ServiceProvider?

Should we have more than one provider available?

Regards,

Peter.

Re: CodebaseAccessClassLoader replacement for RMIClassLoader

Posted by Gregg Wonderly <gr...@wonderly.org>.
In CodebaseAccessClassLoader, I have been thinking that we might need the 
following kind of check to manage exploits that
would know what CodebaseClassAccess instance was being used, and replace it with 
one from another class loader.

     public static void setCodebaseAccessClassLoader( CodebaseClassAccess access ) {
         SecurityManager sm = System.getSecurityManager();
         if( sm != null ) {
             sm.checkPermission(
                 new CodebaseAccessOverridePermission( 
provider.getClass().getName() ) );
         }

         // If the same class is replacing an already existing instance, it 
might be an exploit to
         // load from a different class loader, so don't allow that without the 
replace.classname
         // permission being in place.
         if( provider != null && 
provider.getClass().getName().equals(access.getClass().getName()) &&
             provider.getClass().getClassLoader() != 
access.getClass().getClassLoader() ) {
             sm.checkPermission(new 
CodebaseAccessOverridePermission("replace."+provider.getClass().getName()));
         }
         provider = access;
     }


On 8/11/2012 7:05 PM, Peter Firmstone wrote:
> Peter Firmstone wrote:
>> Just thought I'd get a little clarification on how CodebaseAccessClassLoader 
>> should work and whether it needs any further refinements or tweaks.  I'm 
>> currently patching CodebaseAccessClassLoader back into the main trunk, so it 
>> can make the next release.
>>
>> All references to RMIClassLoader static method calls (except for 
>> RMIClassLoader.getDefaultProviderInstance()) in the platform and supporting 
>> service implementations were replaced with equivalent method calls to 
>> CodebaseAccessClassLoader, I'm now going through the test kits, replacing all 
>> similar method calls.
>>
>> The relationship between PreferredClassProvider, RMIClassLoader and 
>> CodebaseAccessClassLoader appear circular, so I'm finding it a little 
>> confusing how it should be applied in Netbeans or an OSGi environment.
>>
>> Observations:
>>
>>   1. CodebaseAccessClassLoader is the replacement for RMIClassLoader,
>>      it has identical static methods (except for
>>      getDefaultProviderInstance()) and three additional methods
>>      (identical to CodebaseClassAccess).
>>   2. CodebaseAccessClassLoader providers must implement the
>>      CodebaseClassAccess interface, which it delegates to.
>>   3. CodebaseAccessClassLoader has a static method to change the
>>      provider, guarded with a security check.
>>   4. CodebaseClassAccess has identical methods to RMIClassLoader
>>      (except for getDefaultProviderInstance()) and three additional
>>      methods:
>>         1. createClassLoader(URL[] urls, ClassLoader parentLoader,
>>            boolean requiredDlperm, AccessControlContext ctx)
>>         2. getParentContextClassLoader()
>>         3. getSystemContextLoader(ClassLoader defaultLoader).
>>   5. RMIClassLoaderCodebaseAccess is a wrapper around RMIClassLoader
>>      that implements CodebaseClassAccess
>>   6. RMIClassLoaderCodebaseAccess is the default provider for
>>      CodebaseAccessClassLoader
>>   7. PreferredClassProvider doesn't implement CodebaseClassAccess.
>>   8. PreferredClassProvider now calls CodebaseAccessClassLoader to get
>>      the context ClassLoader (which may now be something other than the
>>      call Thread's context ClassLoader) and also calls
>>      CodebaseAccessClassLoader.createClassLoader instead of creating a
>>      PreferredClassLoader directly.
>>   9. Call path CodebaseAccessClassLoader -->
>>      RMIClassLoaderCodebaseAccess --> RMIClassLoader -->
>>      PreferredClassProvider --> CodebaseAccessClassLoader -->
>>      RMIClassLoaderCodebaseAccess
>>  10. The interface CodebaseClassAccess includes deprecated methods from
>>      RMIClassLoader
>>
>> A flaw with the original RMIClassLoaderSPI mechanism is you don't get a 
>> choice of provider, like you do for encryption or other providers, you get 
>> the first loaded provider.  The ServiceProvider mechanism in Java 6 is more 
>> flexible than RMIClassLoaderSPI, allowing loading from child ClassLoaders, 
>> not just the system loader.
>>
>> I understand and appreciate that Gregg has created this to allow development 
>> using Netbeans, a task which the code has proven successful, I also 
>> understand that Chris used it with OSGi. Lets make sure we get it right prior 
>> to release.
>>
>>
>> Some Questions:
>>
>> Should CodebaseAccessClassLoader be used to replace RMIClassLoaderSPI?
>>
>> Shouldn't PreferredClassProvider also implement CodebaseClassAccess?  So it 
>> can be used directly as a provider without using RMIClassLoader or 
>> RMIClassLoaderCodebaseAccess?
>>
>> Shouldn't PreferredClassProvider provide its own methods for creating 
>> ClassLoaders and finding the parent ClassLoader rather than relying on 
>> CodebaseAccessClassLoader, which might be delegating to a different provider.
>>
>> Should we drop the deprecated RMIClassLoader methods?
>
> My mistake, it doesn't contain any deprecated RMIClassLoader methods.
>
>>
>> Should we have additional mechanisms for loading CodebaseAccessClassLoader 
>> providers other than the static setter method?  Eg configuration or 
>> ServiceProvider?
>>
>> Should we have more than one provider available?
>>
>> Regards,
>>
>> Peter.
>>
>
>


Re: CodebaseAccessClassLoader replacement for RMIClassLoader

Posted by Gregg Wonderly <gr...@wonderly.org>.
My initial focus, was on just striping away the dependency on RMIClassLoaderSPI 
as the "only" way to change class loading behavior.  The impetus, of course, was 
that Netbeans does not have a trivial way (let alone functional) way to specify 
a classpath change (required for the static initialization of RMIClassLoaderSPI) 
at startup, without reengineering netbeans itself.  So, I decided that I wanted 
to just make it possible to completely avoid RMIClassLoaderSPI.  The 
optimizations and odd calling paths that you mentioned, were things that I 
looked at, but felt it might be better to go ahead and get some feed back from 
everyone before working on all the changes and optimizations to do all of that.

However, I am sure that PreferredClassProvider really should not be a 
CodebaseClassAccess instance.  There are two usage patterns at play here.

There is the service/client apps, who will assert some CodebaseClassAccess 
instance, and then there is downloaded code, which might use RMI, or which might 
otherwise call PreferredClassProvider.loadClass().  Those  codebases also need 
to be affected by the assertion of a CodebaseClassAccess instance.

I don't remember the exact details of what I experienced when I was putting this 
together, but it seems like I experienced an unexpected call to 
PreferredClassProvider.loadClass().

Note, that my old changes to PreferredClassProvider, to provide deferred 
downloading based on "alwaysPreferred" classes, has been moved into my own 
implementation of CodebaseClassAccess et.al.  I used to have lots of hooks into 
different parts of PreferredClassProvider, including loadClass(), so it may be 
that I'm speaking of past issues which don't exist any longer.

I need to drag all the Netbeans stuff back out and see where things stand it 
appears.

Gregg Wonderly

On 8/11/2012 7:05 PM, Peter Firmstone wrote:
> Peter Firmstone wrote:
>> Just thought I'd get a little clarification on how CodebaseAccessClassLoader 
>> should work and whether it needs any further refinements or tweaks.  I'm 
>> currently patching CodebaseAccessClassLoader back into the main trunk, so it 
>> can make the next release.
>>
>> All references to RMIClassLoader static method calls (except for 
>> RMIClassLoader.getDefaultProviderInstance()) in the platform and supporting 
>> service implementations were replaced with equivalent method calls to 
>> CodebaseAccessClassLoader, I'm now going through the test kits, replacing all 
>> similar method calls.
>>
>> The relationship between PreferredClassProvider, RMIClassLoader and 
>> CodebaseAccessClassLoader appear circular, so I'm finding it a little 
>> confusing how it should be applied in Netbeans or an OSGi environment.
>>
>> Observations:
>>
>>   1. CodebaseAccessClassLoader is the replacement for RMIClassLoader,
>>      it has identical static methods (except for
>>      getDefaultProviderInstance()) and three additional methods
>>      (identical to CodebaseClassAccess).
>>   2. CodebaseAccessClassLoader providers must implement the
>>      CodebaseClassAccess interface, which it delegates to.
>>   3. CodebaseAccessClassLoader has a static method to change the
>>      provider, guarded with a security check.
>>   4. CodebaseClassAccess has identical methods to RMIClassLoader
>>      (except for getDefaultProviderInstance()) and three additional
>>      methods:
>>         1. createClassLoader(URL[] urls, ClassLoader parentLoader,
>>            boolean requiredDlperm, AccessControlContext ctx)
>>         2. getParentContextClassLoader()
>>         3. getSystemContextLoader(ClassLoader defaultLoader).
>>   5. RMIClassLoaderCodebaseAccess is a wrapper around RMIClassLoader
>>      that implements CodebaseClassAccess
>>   6. RMIClassLoaderCodebaseAccess is the default provider for
>>      CodebaseAccessClassLoader
>>   7. PreferredClassProvider doesn't implement CodebaseClassAccess.
>>   8. PreferredClassProvider now calls CodebaseAccessClassLoader to get
>>      the context ClassLoader (which may now be something other than the
>>      call Thread's context ClassLoader) and also calls
>>      CodebaseAccessClassLoader.createClassLoader instead of creating a
>>      PreferredClassLoader directly.
>>   9. Call path CodebaseAccessClassLoader -->
>>      RMIClassLoaderCodebaseAccess --> RMIClassLoader -->
>>      PreferredClassProvider --> CodebaseAccessClassLoader -->
>>      RMIClassLoaderCodebaseAccess
>>  10. The interface CodebaseClassAccess includes deprecated methods from
>>      RMIClassLoader
>>
>> A flaw with the original RMIClassLoaderSPI mechanism is you don't get a 
>> choice of provider, like you do for encryption or other providers, you get 
>> the first loaded provider.  The ServiceProvider mechanism in Java 6 is more 
>> flexible than RMIClassLoaderSPI, allowing loading from child ClassLoaders, 
>> not just the system loader.
>>
>> I understand and appreciate that Gregg has created this to allow development 
>> using Netbeans, a task which the code has proven successful, I also 
>> understand that Chris used it with OSGi. Lets make sure we get it right prior 
>> to release.
>>
>>
>> Some Questions:
>>
>> Should CodebaseAccessClassLoader be used to replace RMIClassLoaderSPI?
>>
>> Shouldn't PreferredClassProvider also implement CodebaseClassAccess?  So it 
>> can be used directly as a provider without using RMIClassLoader or 
>> RMIClassLoaderCodebaseAccess?
>>
>> Shouldn't PreferredClassProvider provide its own methods for creating 
>> ClassLoaders and finding the parent ClassLoader rather than relying on 
>> CodebaseAccessClassLoader, which might be delegating to a different provider.
>>
>> Should we drop the deprecated RMIClassLoader methods?
>
> My mistake, it doesn't contain any deprecated RMIClassLoader methods.
>
>>
>> Should we have additional mechanisms for loading CodebaseAccessClassLoader 
>> providers other than the static setter method?  Eg configuration or 
>> ServiceProvider?
>>
>> Should we have more than one provider available?
>>
>> Regards,
>>
>> Peter.
>>
>
>


Re: CodebaseAccessClassLoader replacement for RMIClassLoader

Posted by Peter Firmstone <ji...@zeus.net.au>.
Peter Firmstone wrote:
> Just thought I'd get a little clarification on how 
> CodebaseAccessClassLoader should work and whether it needs any further 
> refinements or tweaks.  I'm currently patching 
> CodebaseAccessClassLoader back into the main trunk, so it can make the 
> next release.
>
> All references to RMIClassLoader static method calls (except for 
> RMIClassLoader.getDefaultProviderInstance()) in the platform and 
> supporting service implementations were replaced with equivalent 
> method calls to CodebaseAccessClassLoader, I'm now going through the 
> test kits, replacing all similar method calls.
>
> The relationship between PreferredClassProvider, RMIClassLoader and 
> CodebaseAccessClassLoader appear circular, so I'm finding it a little 
> confusing how it should be applied in Netbeans or an OSGi environment.
>
> Observations:
>
>   1. CodebaseAccessClassLoader is the replacement for RMIClassLoader,
>      it has identical static methods (except for
>      getDefaultProviderInstance()) and three additional methods
>      (identical to CodebaseClassAccess).
>   2. CodebaseAccessClassLoader providers must implement the
>      CodebaseClassAccess interface, which it delegates to.
>   3. CodebaseAccessClassLoader has a static method to change the
>      provider, guarded with a security check.
>   4. CodebaseClassAccess has identical methods to RMIClassLoader
>      (except for getDefaultProviderInstance()) and three additional
>      methods:
>         1. createClassLoader(URL[] urls, ClassLoader parentLoader,
>            boolean requiredDlperm, AccessControlContext ctx)
>         2. getParentContextClassLoader()
>         3. getSystemContextLoader(ClassLoader defaultLoader).
>   5. RMIClassLoaderCodebaseAccess is a wrapper around RMIClassLoader
>      that implements CodebaseClassAccess
>   6. RMIClassLoaderCodebaseAccess is the default provider for
>      CodebaseAccessClassLoader
>   7. PreferredClassProvider doesn't implement CodebaseClassAccess.
>   8. PreferredClassProvider now calls CodebaseAccessClassLoader to get
>      the context ClassLoader (which may now be something other than the
>      call Thread's context ClassLoader) and also calls
>      CodebaseAccessClassLoader.createClassLoader instead of creating a
>      PreferredClassLoader directly.
>   9. Call path CodebaseAccessClassLoader -->
>      RMIClassLoaderCodebaseAccess --> RMIClassLoader -->
>      PreferredClassProvider --> CodebaseAccessClassLoader -->
>      RMIClassLoaderCodebaseAccess
>  10. The interface CodebaseClassAccess includes deprecated methods from
>      RMIClassLoader
>
> A flaw with the original RMIClassLoaderSPI mechanism is you don't get 
> a choice of provider, like you do for encryption or other providers, 
> you get the first loaded provider.  The ServiceProvider mechanism in 
> Java 6 is more flexible than RMIClassLoaderSPI, allowing loading from 
> child ClassLoaders, not just the system loader.
>
> I understand and appreciate that Gregg has created this to allow 
> development using Netbeans, a task which the code has proven 
> successful, I also understand that Chris used it with OSGi.  Lets make 
> sure we get it right prior to release.
>
>
> Some Questions:
>
> Should CodebaseAccessClassLoader be used to replace RMIClassLoaderSPI?
>
> Shouldn't PreferredClassProvider also implement CodebaseClassAccess?  
> So it can be used directly as a provider without using RMIClassLoader 
> or RMIClassLoaderCodebaseAccess?
>
> Shouldn't PreferredClassProvider provide its own methods for creating 
> ClassLoaders and finding the parent ClassLoader rather than relying on 
> CodebaseAccessClassLoader, which might be delegating to a different 
> provider.
>
> Should we drop the deprecated RMIClassLoader methods?

My mistake, it doesn't contain any deprecated RMIClassLoader methods.

>
> Should we have additional mechanisms for loading 
> CodebaseAccessClassLoader providers other than the static setter 
> method?  Eg configuration or ServiceProvider?
>
> Should we have more than one provider available?
>
> Regards,
>
> Peter.
>