Re: WebObjects classloader fun.
Re: WebObjects classloader fun.
- Subject: Re: WebObjects classloader fun.
- From: Q <email@hidden>
- Date: Fri, 30 Mar 2007 15:45:42 +1000
On 30/03/2007, at 2:44 PM, Mike Schrag wrote:
Does anyone know much about how webobjects uses the classloader
and how the _NSUtilities class cache is initialized and used?
[snip] it appears that _NSUtilities has a static initialiser that
pulls in and caches classes rather than asking the current thread
context classloader for them when needed [snip]
You are correct ... Frameworks (and your app) are loaded by
NSBundle, which traverses all of the classpath and loads the
reachable classes into the NSUtilities cache (so you can do things
like looking up a component by name -- _NSUtilities.classWithName
(..)). You can also override these class names by calling
_NSUtilities.setClassForName. If the name was not in the cache, it
will Class.forName it and then put the result into the cache. This
behavior makes packageless WOComponent name lookups (for instance)
very fast in exchange for some kind of weird behavior (like cross-
your-fingers-if-you-have-two-classes-with-the-same-name).
That kinda sucks. As it means that I cannot intercept the call to
Class.forName() as it doesn't use the thread context class loader,
but instead the classloader that loaded _NSUtilities, (ie. the system
class loader). This therefore means I either need to bootstrap the
application differently so that the classloader chain is setup before
_NSUtilities is loaded (like how groovy bootstraps its script files),
or I need to dynamically compile every single new or changed .groovy
file in the classpath ahead of time so that the system class loader
can resolve them, which I think would probably work, but is far more
complicated than I was hoping for.
Unfortunately, I don't know of any way to REMOVE an entry from the
cache. You can't setClassForName(null, "ClassName") because that
tries to put a null key into the cache. If you specifically know
the class name, you can replace it yourself -- ERXPatcher is
generally just calling setClassForName with classes it replaces
You need to use reflection to do that so you can poke at the
underlying dictionary directly, which isn't pretty, but it works.
--
Seeya...Q
Quinton Dolan - email@hidden
Gold Coast, QLD, Australia
Ph: +61 419 729 806
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden