db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Dag H. Wanvik" <Dag.Wan...@Sun.COM>
Subject Re: [PATCH] (DERBY-205; 2nd patch) org.apache.derby.impl.drda.DB2jServerImpl to NetworkServerControlImpl
Date Fri, 27 May 2005 00:29:07 GMT
Hi,

>>>>> "KM" == Kathey Marsden <kmarsdenderby@sbcglobal.net> wrote:

KM> If you shutdown derby with
KM> DriverManager.getConnection("jdbc:derby:;shutdown=true");
KM> then set the next property and start it back up again, will that work?

This seems to be a necessary but not sufficient condition, see
non-obvious requirement below.

>>>>> "OB" == Oyvind Bakksjo <Oyvind.Bakksjo@Sun.COM> wrote:
OB> Yes, system properties are VM-wide, but they can be changed at any time. 
OB> The problem is if the properties are read and used only once, when the 
OB> driver is loaded, since it is impossible to instruct a class loader to 
OB> "unload" anything.

Derby docs says this can be achieved by forcing the garbage collector to
run, cf the hint I found here, see quote below.

http://incubator.apache.org/derby/docs/devguide/tdevdvlp20349.html

(quote): To restart Derby successfully, the JVM needs to unload
         org.apache.derby.jdbc.EmbeddedDriver, so that it can reload
	 it when it restarts Derby. (Loading the local driver starts
	 Derby.)  You cannot explicitly request that the JVM unload a
	 class, but you can ensure that the EmbeddedDriver class is
	 unloaded by using a System.gc() to force it to garbage
	 collect classes that are no longer needed. Running with -nogc
	 or -noclassgc definitely prevents the class from being
	 unloaded and makes you unable to restart Derby in the same
	 JVM.

I found the following idiom worked:

	    <set properties>
	    Class.forName(driver).newInstance();   <--- newInstance can be dropped 1. time!!
	    <use derby>
	    DriverManager.getConnection("jdbc:derby:;shutdown=true");

	    System.gc();                           <--- in vain?

	    <set new properties>
	    Class.forName(driver).newInstance();   <---- but necessary here!
	    <use derby with new properties>
	    DriverManager.getConnection("jdbc:derby:;shutdown=true");

Note: newInstance() was needed the second time around.  Plain
"Class.forName(driver)" wont do, it gives:

  SQLException: 08001:No suitable driver

when I try to make a connection, i.e. the driver has not
(re)registered itself with the DriverManager The driver's static
initializer hasn't been run (again), cf. description in JDBC 3.0 spec
section 9.2. This leads me to believe the driver hasn't been evicted
by the gc() call after all. Why not? Did I miss something?

However, adding newInstance() makes it work.  Checking the code, I
found this in EmbeddedDriver, which explains why it works; the
constructor forces a reboot.

	static {

		EmbeddedDriver.boot();            
	}

	// Boot from the constructor as well to ensure that
	// Class.forName(...).newInstance() reboots Cloudscape
	// after a shutdown inside the same JVM.
	public EmbeddedDriver() {
		EmbeddedDriver.boot();
	}

Hmm... Should Derby docs mention using newInstance? Is it Kosher? The
JDBC spec doesnt say anything about using newInstance...

Not only Derby needs this, however, cf. also this discussion I found:

https://lists.xcf.berkeley.edu/lists/advanced-java/2000-September/012601.html

Dag

Mime
View raw message