Re: context classloader - Mailing list pgsql-jdbc
From | Oliver Jowett |
---|---|
Subject | Re: context classloader |
Date | |
Msg-id | 41EDDE4B.7030304@opencloud.com Whole thread Raw |
In response to | Re: context classloader (Vadim Nasardinov <vadimn@redhat.com>) |
Responses |
Re: context classloader
Re: context classloader |
List | pgsql-jdbc |
Vadim Nasardinov wrote: > On Tuesday 18 January 2005 18:07, Oliver Jowett wrote: > >>I am of the opinion that thread context classloaders are evil > > > If that's a moral judgment, I have no comment. If a technical one -- > where's the evidence? (My ignorance prevents me from taking sides in > this argument. I'm just curious.) It's just an opinion. I have been bitten by context classloader weirdness often enough that I try to avoid it whenever I can. If you use the CCL, you have added hidden coupling between whoever sets the CCL and the use of the CCL. Hidden coupling is usually bad -- it makes the code less obvious and more prone to context-sensitive breakage. Many libraries depend on particular CCL settings *and do not document this anywhere*. Really hidden coupling! It gets worse if you are in a managed environment -- the environment may be using the CCL for its own purposes, and your code may not even have permission (security policy) to change the CCL. To use a CCL-using library reliably in that sort of environment, you end up setting and resetting the CCL on every call to the library (might involve writing a privileged wrapper -- ugh!). This defeats the purpose of having a CCL in the first place. Why not just configure the library with the right ClassLoader via another mechanism, or explicitly pass a ClassLoader to those methods that need to do class/resource loading? Sorry .. it's a pet peeve of mine :) Given that there is a non-ClassLoader-aware layer (DriverManager) between the JDBC client and JDBC driver that we cannot change, if we needed to pass a ClassLoader then using the CCL is probably the best way. But I don't see that we *need* to pass a ClassLoader at all; see below. > When you register the Driver instance with the DriverManager in the > static initializer, a (weak) reference to the current context > classloader may be saved in a static field. The field can be used > later on in the getDefaultProperties() method, if > getClass().getClassLoader() turns out to be null. Ok, but I don't understand why you'd want to jump through all these hoops in the first place. 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? > (BTW, couldn't this > be Driver.class.getClassLoader() instead?) 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. >>Does it make sense to have the driver defaults change depending on >>who is obtaining the connection? > > The fact that this is nonsensical is irrelevant. Changing defaults on > a per connection basis has never been proposed. *shrug* It's the logical conclusion of using the CCL to find the defaults. The context can change -- why do the defaults *not* change if you change the context? What is special about the context of the first call to getConnection(), or the first action that happens to cause class initialization (if you go with magic in the static initializer)? > More to the point, can someone explain what > /org/postgresql/driverconfig.properties files are actually used for? Briefly, configuring driver defaults globally without having to mess around with every application URL. See http://archives.postgresql.org/pgsql-jdbc/2004-10/msg00023.php for the thread that spawned it. > Without knowing what this feature is actually used for, I'd speculate > groundlessly that the context-classloader-based implementation is more > likely to work in the application server scenario. Within the same > app server instance, multiple *.properties files are likely to exist > for use by different apps. These files aren't likely to be on the > CLASSPATH. I don't think it makes sense to allow a particular application to override a bit of "global" data for the driver that is shared between multiple applications. App servers can reconfigure the driver either globally or on a per-application basis easily enough anyway. > Rather, they're likely to be in a per-application config directory that the system classloader can't see. The system classloader only gets involved when the driver has been loaded in the *bootstrap* classpath. In all other cases, we use the classloader that loaded the driver to load the defaults. Still, this will usually be a classloader that cannot see the per-application resources. If an application wants a customized set of defaults, it can arrange for a separate instance of the driver packaged with the appropriate defaults to be loaded with the application; in that case, there's no problem with finding the right classloader. -O
pgsql-jdbc by date: