Dag H. Wanvik wrote:
Hi,
"KM" == Kathey Marsden <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> 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");
Should a finalize be forced after this happens? May be gc() can pick this?
Or deregister the driver from the DriverManager?
~ Shreyas
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