You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-dev@db.apache.org by "David W. Van Couvering" <Da...@Sun.COM> on 2005/11/23 00:41:49 UTC

context classloader versus default classloader

Hi.  I am a little confused between two different "current classloaders" 
that are available to appication code:

this.getClass().getClassLoader() -- what I call the "default classloader"

Thread.currentThread.getContextClassLoader() -- what I call the "context 
classloader"

When I am creating my own classloader, I want to identify the parent 
classloader.  Which one of these should I use?  I noticed that the 
engine code uses the context classloader to load application classes, 
but sets the default classloader to be its parent when creating a 
classloader for loading generated bytecode.

Any and all tips would be most appreciated.

Thanks,

David

Re: context classloader versus default classloader

Posted by "David W. Van Couvering" <Da...@Sun.COM>.
My knowledge is increasing...

A great white paper:

http://www.theserverside.com/articles/content/dm_classForname/DynLoad.pdf

It appears that the context classloader is made available to code to use 
*if they want to* but is not implicitly used when using 
'Class.forName()' or 'new XXX()'.

David

David W. Van Couvering wrote:
> A quick note: it appears I'm not the only one who struggles with this 
> problem...
> 
> http://jroller.com/page/alanli?entry=plugin_architecture_thread_context_classloader 
> 
> 
> David W. Van Couvering wrote:
> 
>> Hi.  I am a little confused between two different "current 
>> classloaders" that are available to appication code:
>>
>> this.getClass().getClassLoader() -- what I call the "default classloader"
>>
>> Thread.currentThread.getContextClassLoader() -- what I call the 
>> "context classloader"
>>
>> When I am creating my own classloader, I want to identify the parent 
>> classloader.  Which one of these should I use?  I noticed that the 
>> engine code uses the context classloader to load application classes, 
>> but sets the default classloader to be its parent when creating a 
>> classloader for loading generated bytecode.
>>
>> Any and all tips would be most appreciated.
>>
>> Thanks,
>>
>> David

Re: context classloader versus default classloader

Posted by "David W. Van Couvering" <Da...@Sun.COM>.
A quick note: it appears I'm not the only one who struggles with this 
problem...

http://jroller.com/page/alanli?entry=plugin_architecture_thread_context_classloader

David W. Van Couvering wrote:
> Hi.  I am a little confused between two different "current classloaders" 
> that are available to appication code:
> 
> this.getClass().getClassLoader() -- what I call the "default classloader"
> 
> Thread.currentThread.getContextClassLoader() -- what I call the "context 
> classloader"
> 
> When I am creating my own classloader, I want to identify the parent 
> classloader.  Which one of these should I use?  I noticed that the 
> engine code uses the context classloader to load application classes, 
> but sets the default classloader to be its parent when creating a 
> classloader for loading generated bytecode.
> 
> Any and all tips would be most appreciated.
> 
> Thanks,
> 
> David

Re: context classloader versus default classloader

Posted by Daniel John Debrunner <dj...@debrunners.com>.
David W. Van Couvering wrote:

> Yes, great background info.  I am a little concerned about the
> classloading work I am doing clashing with your security work.  I am
> thinking of changing getApplicationClass() to load org.apache.derby
> classes with the default classloader as you suggest -- is that going to
> step on your toes?

I don't think so, it's the same general direction as I'm heading.

Dan.



Re: context classloader versus default classloader

Posted by "David W. Van Couvering" <Da...@Sun.COM>.
Yes, great background info.  I am a little concerned about the 
classloading work I am doing clashing with your security work.  I am 
thinking of changing getApplicationClass() to load org.apache.derby 
classes with the default classloader as you suggest -- is that going to 
step on your toes?

David

Daniel John Debrunner wrote:
> David W. Van Couvering wrote:
> 
> 
>>The concern I have is that DatabaseClasses.loadApplicationClass() uses
>>the thread context classloader, and if the class is not found there (or
>>there is no context classloader), only then does it use the default
>>classloader.
>>
>>Let's say I'm able to create a classloader whose search path only
>>includes specific derby jar files (to avoid the issues of mixed versions
>>of Derby).
>>
>>Then let's say I try to make use of this when getting connections:
>>
>>URLClassLoader cl = new MyClassLoader()
>>EmbeddedDataSource ds =
>>(EmbeddedDataSource)(cl.loadClass("org.apache.derby.jdbc.EmbeddedDataSource").newInstance())
>>
>>Connection conn = ds.getConnection(...);
> 
> 
> Of course the variable ds here would have to be declared as
> javax.sql.DataSource and not EmbeddedDataSource. :-)
> 
> 
>>This effectively sets the default classloader for EmbeddedDataSource
>>(and all its dependent classes) to be MyClassLoader.
>>
>>What I am concerned about is that there is all this code in the Derby
>>engine that calls DatabaseClasses.loadApplicationClass().  It looks like
>>this is used to load classes for VTIs and Java stored procedures (it's
>>hard to tell) as well as a number of other things I'm not clear on.  If
>>any of these classes are Derby classes (for instance internal VTIs) then
>>it would seem that my attempt to correctly load Derby classes from the
>>right jar files will be thwarted.
> 
> 
> So the use of the class context class loader was added for J2EE
> applications. In those the application's classes for procedures,
> functions, vti's etc. can be stored in the WAR or EAR file, and those
> classes are available to the system through the context class loader.
> The context class loader is set up by the container manager, ie. the
> application server, WAS or Geronimo etc.
> 
> 
>>Probably the right thing for me to do is test this, but if you have any
>>observations about this that might guide me it would be much appreciated.
> 
> 
> One of the changes I made to the Cloudscape code before it was open
> sourced as Derby, was to separate the packages at a high level.
> Previously all the code, product and tests, had a common package prefix,
> COM.cloudscape or com.ibm.db2j. This meant there was no way to tell from
> a class name if the class was a Derby class or a test class (e.g.
> function). With Derby I separated the code so that tests were all under
> org.apache.derbyTesting and product under org.apache.derby (and some
> other splits.) This then allows (though it's not done yet) class loading
> code to be more precise in loading classes, since it's obvious that any
> org.apache.derby. class is  part of the system and not a test procedure etc.
> 
> As an example, related to the security changes I'm working on, I'm
> thinking about making the class loaders for the application installed
> jars (sqlj.install_jar) refuse to load any class starting with the
> prefix 'org.apache.derby.'. This would then remove one potential hole
> where an application could try to subvert an engine class.
> 
> There may be similar possible changes for loadApplicationClass(), don't
> load org.apache.derby. classes through the context class loader.
> 
> It may be that ensuring the classes are loaded from the same jar/class
> loader is good for security and for the multi-version issue.
> 
> In addition most of the packages in derby.jar are now sealed, which
> means that classes in a sealed package must be loaded from the same jar.
>  This is not sufficient because if a class is loaded from another jar an
> error is thrown rather than ignoring the load. Thus, without changes, an
> application can try to subvert and inject invalid versions of Derby
> classes, which will not be accepted by the vm, but could cause a denial
> of service.
> 
> Hope this helps as background info.
> Dan.
> 
> 

Re: context classloader versus default classloader

Posted by Daniel John Debrunner <dj...@debrunners.com>.
David W. Van Couvering wrote:

> The concern I have is that DatabaseClasses.loadApplicationClass() uses
> the thread context classloader, and if the class is not found there (or
> there is no context classloader), only then does it use the default
> classloader.
> 
> Let's say I'm able to create a classloader whose search path only
> includes specific derby jar files (to avoid the issues of mixed versions
> of Derby).
> 
> Then let's say I try to make use of this when getting connections:
> 
> URLClassLoader cl = new MyClassLoader()
> EmbeddedDataSource ds =
> (EmbeddedDataSource)(cl.loadClass("org.apache.derby.jdbc.EmbeddedDataSource").newInstance())
> 
> Connection conn = ds.getConnection(...);

Of course the variable ds here would have to be declared as
javax.sql.DataSource and not EmbeddedDataSource. :-)

> This effectively sets the default classloader for EmbeddedDataSource
> (and all its dependent classes) to be MyClassLoader.
> 
> What I am concerned about is that there is all this code in the Derby
> engine that calls DatabaseClasses.loadApplicationClass().  It looks like
> this is used to load classes for VTIs and Java stored procedures (it's
> hard to tell) as well as a number of other things I'm not clear on.  If
> any of these classes are Derby classes (for instance internal VTIs) then
> it would seem that my attempt to correctly load Derby classes from the
> right jar files will be thwarted.

So the use of the class context class loader was added for J2EE
applications. In those the application's classes for procedures,
functions, vti's etc. can be stored in the WAR or EAR file, and those
classes are available to the system through the context class loader.
The context class loader is set up by the container manager, ie. the
application server, WAS or Geronimo etc.

> Probably the right thing for me to do is test this, but if you have any
> observations about this that might guide me it would be much appreciated.

One of the changes I made to the Cloudscape code before it was open
sourced as Derby, was to separate the packages at a high level.
Previously all the code, product and tests, had a common package prefix,
COM.cloudscape or com.ibm.db2j. This meant there was no way to tell from
a class name if the class was a Derby class or a test class (e.g.
function). With Derby I separated the code so that tests were all under
org.apache.derbyTesting and product under org.apache.derby (and some
other splits.) This then allows (though it's not done yet) class loading
code to be more precise in loading classes, since it's obvious that any
org.apache.derby. class is  part of the system and not a test procedure etc.

As an example, related to the security changes I'm working on, I'm
thinking about making the class loaders for the application installed
jars (sqlj.install_jar) refuse to load any class starting with the
prefix 'org.apache.derby.'. This would then remove one potential hole
where an application could try to subvert an engine class.

There may be similar possible changes for loadApplicationClass(), don't
load org.apache.derby. classes through the context class loader.

It may be that ensuring the classes are loaded from the same jar/class
loader is good for security and for the multi-version issue.

In addition most of the packages in derby.jar are now sealed, which
means that classes in a sealed package must be loaded from the same jar.
 This is not sufficient because if a class is loaded from another jar an
error is thrown rather than ignoring the load. Thus, without changes, an
application can try to subvert and inject invalid versions of Derby
classes, which will not be accepted by the vm, but could cause a denial
of service.

Hope this helps as background info.
Dan.



Re: context classloader versus default classloader

Posted by "David W. Van Couvering" <Da...@Sun.COM>.

Oyvind.Bakksjo@Sun.COM wrote:
> David W. Van Couvering wrote:
> 
> To avoid those issues, you need to make sure that your classloader does 
> not delegate loading of Derby classes to its parents. You don't need to 
> restrict the search path of your classloader to *only* derby jar files.
>

yes, OK

>> Then let's say I try to make use of this when getting connections:
>>
>> URLClassLoader cl = new MyClassLoader()
>> EmbeddedDataSource ds = 
>> (EmbeddedDataSource)(cl.loadClass("org.apache.derby.jdbc.EmbeddedDataSource").newInstance()) 
> 
> 
> 
> If you write code like this, the declaration of ds causes a load of 
> EmbeddedDataSource through the default classloader. If this classloader 
> cannot load Derby, you will get an exception before getting to 
> cl.loadClass(). If it *is* able to load Derby, ds will be of a different 
> class than the one loaded with cl.loadClass(), so the assignment will 
> throw a ClassCastException.

Well, I was going to test this, because I wasn't sure how this worked. 
But what you say makes sense, thanks.

Still ruminating on this...

David


Re: context classloader versus default classloader

Posted by Oy...@Sun.COM.
David W. Van Couvering wrote:
> The concern I have is that DatabaseClasses.loadApplicationClass() uses 
> the thread context classloader, and if the class is not found there (or 
> there is no context classloader), only then does it use the default 
> classloader.
> 
> Let's say I'm able to create a classloader whose search path only 
> includes specific derby jar files (to avoid the issues of mixed versions 
> of Derby).

To avoid those issues, you need to make sure that your classloader does 
not delegate loading of Derby classes to its parents. You don't need to 
restrict the search path of your classloader to *only* derby jar files.

> Then let's say I try to make use of this when getting connections:
> 
> URLClassLoader cl = new MyClassLoader()
> EmbeddedDataSource ds = 
> (EmbeddedDataSource)(cl.loadClass("org.apache.derby.jdbc.EmbeddedDataSource").newInstance()) 

If you write code like this, the declaration of ds causes a load of 
EmbeddedDataSource through the default classloader. If this classloader 
cannot load Derby, you will get an exception before getting to 
cl.loadClass(). If it *is* able to load Derby, ds will be of a different 
class than the one loaded with cl.loadClass(), so the assignment will 
throw a ClassCastException.

> Connection conn = ds.getConnection(...);
> 
> This effectively sets the default classloader for EmbeddedDataSource 
> (and all its dependent classes) to be MyClassLoader.

Yes, the default classloader for any class is the classloader it was 
loaded with.

-- 
Oyvind Bakksjo
Sun Microsystems, Database Technology Group
Trondheim, Norway
http://weblogs.java.net/blog/bakksjo/

Re: context classloader versus default classloader

Posted by "David W. Van Couvering" <Da...@Sun.COM>.
The concern I have is that DatabaseClasses.loadApplicationClass() uses 
the thread context classloader, and if the class is not found there (or 
there is no context classloader), only then does it use the default 
classloader.

Let's say I'm able to create a classloader whose search path only 
includes specific derby jar files (to avoid the issues of mixed versions 
of Derby).

Then let's say I try to make use of this when getting connections:

URLClassLoader cl = new MyClassLoader()
EmbeddedDataSource ds = 
(EmbeddedDataSource)(cl.loadClass("org.apache.derby.jdbc.EmbeddedDataSource").newInstance())
Connection conn = ds.getConnection(...);

This effectively sets the default classloader for EmbeddedDataSource 
(and all its dependent classes) to be MyClassLoader.

What I am concerned about is that there is all this code in the Derby 
engine that calls DatabaseClasses.loadApplicationClass().  It looks like 
this is used to load classes for VTIs and Java stored procedures (it's 
hard to tell) as well as a number of other things I'm not clear on.  If 
any of these classes are Derby classes (for instance internal VTIs) then 
it would seem that my attempt to correctly load Derby classes from the 
right jar files will be thwarted.

Probably the right thing for me to do is test this, but if you have any 
observations about this that might guide me it would be much appreciated.

Thanks,

David


Daniel John Debrunner wrote:
> David W. Van Couvering wrote:
> 
> 
>>Hi.  I am a little confused between two different "current classloaders"
>>that are available to appication code:
>>
>>this.getClass().getClassLoader() -- what I call the "default classloader"
>>
>>Thread.currentThread.getContextClassLoader() -- what I call the "context
>>classloader"
>>
>>When I am creating my own classloader, I want to identify the parent
>>classloader.  Which one of these should I use?  I noticed that the
>>engine code uses the context classloader to load application classes,
>>but sets the default classloader to be its parent when creating a
>>classloader for loading generated bytecode.
>>
>>Any and all tips would be most appreciated.
> 
> 
> I guess a lot depends on why you are creating the class loader.
> 
> The context class loader is specific to the current thread and can be
> short lived. Thus assigning the current thread's context class loader to
> an object that can be shared by multiple threads, or one that may live
> longer than the current thread seems to make no sense.
> 
> Dan.
> 

Re: context classloader versus default classloader

Posted by Daniel John Debrunner <dj...@debrunners.com>.
David W. Van Couvering wrote:

> Hi.  I am a little confused between two different "current classloaders"
> that are available to appication code:
> 
> this.getClass().getClassLoader() -- what I call the "default classloader"
> 
> Thread.currentThread.getContextClassLoader() -- what I call the "context
> classloader"
> 
> When I am creating my own classloader, I want to identify the parent
> classloader.  Which one of these should I use?  I noticed that the
> engine code uses the context classloader to load application classes,
> but sets the default classloader to be its parent when creating a
> classloader for loading generated bytecode.
> 
> Any and all tips would be most appreciated.

I guess a lot depends on why you are creating the class loader.

The context class loader is specific to the current thread and can be
short lived. Thus assigning the current thread's context class loader to
an object that can be shared by multiple threads, or one that may live
longer than the current thread seems to make no sense.

Dan.