Re: context classloader - Mailing list pgsql-jdbc

From Oliver Jowett
Subject Re: context classloader
Date
Msg-id 41EEC8E1.1010007@opencloud.com
Whole thread Raw
In response to Re: context classloader  (Vadim Nasardinov <vadimn@redhat.com>)
Responses Re: context classloader
List pgsql-jdbc
Vadim Nasardinov wrote:
> On Tuesday 18 January 2005 23:12, Oliver Jowett wrote:

>>It is even less predictable when the static initializer will be run
>>(and therefore what the CCL will be set to at that point). What's
>>the point?
>
> The same goes for getClass().getClassLoader().  It's not predictable
> what this returns.

Two comments:

Firstly, your statement is not true. getClass().getClassLoader() will
always return the classloader that was used to load the driver class,
which *is* predictable. You can always, for example, put
driverconfig.properties in the path of the same classloader that loads
the driver (at worst, by packaging it directly in the driver jar) and
the driver will find it. In contrast, if you're relying on the CCL, you
have essentially no guarantees about where it will search. It could be a
completely unrelated CL that can't even see the driver jar!

Secondly, I think you missed my point. It is the *timing* of
initialization that I am concerned about. Timing of class initialization
is hard to predict; how do you make sure that the CCL is correctly set
when this happens? How do you document this so that users don't get
confused? It seems unreasonable to require someone who just wants to use
the JDBC driver to have to understand the mechanics of class
initialization and guard against accidentally causing initialization
before they're ready!

>>What is special about [...] the first action that happens to cause
>>class initialization (if you go with magic in the static
>>initializer)?
>
> It's special because it determines the result of
> getClass().getClassLoader().

It does not. getClass().getClassLoader() always returns the classloader
that loaded org.postgresql.Driver, regardless of the environment when
class initialization is triggered. The returned classloader will not
change during the lifetime of a particular copy of the Driver class.

If you are using the CCL to locate the defaults, then either the context
set during initialization is somehow special (if you only load the
defaults once) or you must load the defaults on every getConnection()
and they can change depending on the caller's context. I don't like
either behaviour.

> For the sake of completeness, what do you think of doing nothing in
> the case when the driver is loaded by the bootstrap classloader?  In
> other words, wrap the affected chunk of code in the following
> conditional:
>
>         if (getClass().getClassLoader() != null) {
>             // load the /org/postgresql/driverconfig.properties files
>         }

It could do that (it does that if the system classloader is null) but it
seems less useful -- why can the driver suddenly no longer load defaults
if it ends up in the bootstrap classpath?

Ideally we need some way to get resources directly from the bootstrap
classloader, but ClassLoader does not give us a way to do that. Using
the system classloader seems like the best approximation.

>>Yes. getClass() tends to be a bit friendlier to anything that tweaks
>>the bytecode, though, since a .class reference compiles down to a
>>call to Class.forName() which breaks if the class is renamed, etc.
>
> Out of curiosity, is it a formal policy of the pgsql-jdbc project to
> be friendly to bytecode mungers?  What other guidelines does one need
> to be mindful of?

Personally I write lots of other code that has to be friendly to
bytecode mungers, so it becomes force of habit. It's not a formal
policy, just one of my own code hygiene rules.

-O

pgsql-jdbc by date:

Previous
From:
Date:
Subject: unsubscribe
Next
From: Avramucz István
Date:
Subject: DataSource