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.