On 10/22/2012 6:44 AM, Katherine Marsden wrote:

I have some code that shows the behavior


Here is the program showing the behavior:

import java.io.*;
import java.net.*;
import java.sql.*;
import javax.sql.*;
import javax.transaction.xa.*;

public class TestDerbyInMemoryDatabase
{
    private final static String DB_NAME = "memory:testdb";
private final static String JAR_LOCATION="file:///C:/cygwin/svnreleases/jars/10.8.2.2/derby.jar";

private static void insert(int value, ClassLoader loader) throws Exception
    {
        @SuppressWarnings("unchecked")
Class<DataSource> dsClass = (Class<DataSource>) loader.loadClass("org.apache.derby.jdbc.EmbeddedDataSource40");
        DataSource ds = dsClass.newInstance();
dsClass.getMethod("setDatabaseName", String.class).invoke(ds, DB_NAME); dsClass.getMethod("setCreateDatabase", String.class).invoke(ds, "create");

        Connection con = ds.getConnection();
        Statement stmt = con.createStatement();

        try {
stmt.executeUpdate("create table tbl1 (col1 int not null primary key)");
            System.out.println("created new table");
        } catch (SQLException x) {
            System.out.println(x.getMessage());
        }

        stmt.executeUpdate("insert into tbl1 values (" + value + ")");
        System.out.println("inserted " + value);

        ResultSet result = stmt.executeQuery("select * from tbl1");
        System.out.print("contents of table: ");
        while (result.next())
            System.out.print(result.getInt(1) + " ");
        System.out.println();

        con.close();
    }

    private static void shutdown(ClassLoader loader) throws Exception {
        @SuppressWarnings("unchecked")
Class<DataSource> dsClass = (Class<DataSource>) loader.loadClass("org.apache.derby.jdbc.EmbeddedDataSource40");

        DataSource ds = dsClass.newInstance();
dsClass.getMethod("setDatabaseName", String.class).invoke(ds, DB_NAME); dsClass.getMethod("setShutdownDatabase", String.class).invoke(ds, "shutdown");
        try {
            ds.getConnection();
            throw new Exception();
        } catch (SQLException x) {
            if (45000 == x.getErrorCode())
                System.out.println(x.getMessage());
            else
                throw x;
        }

        ds = dsClass.newInstance();
dsClass.getMethod("setShutdownDatabase", String.class).invoke(ds, "shutdown");
        try {
            ds.getConnection();
            throw new Exception();
        } catch (SQLException x) {
            if ("XJ015".equals(x.getSQLState()))
                System.out.println(x.getMessage());
            else
                throw x;
        }
    }

    public static void main(String[] args) throws Throwable
    {
        URL[] urls = new URL[] { new URL(JAR_LOCATION) };
        ClassLoader derbyLoader1 = new URLClassLoader(urls);

        insert(1, derbyLoader1);
        shutdown(derbyLoader1);

        ClassLoader derbyLoader2 = new URLClassLoader(urls);
        insert(2, derbyLoader2);
        shutdown(derbyLoader2);

        insert(3, derbyLoader1);
        shutdown(derbyLoader1);
    }
}

The program creates a table and inserts an entry (1), then shuts down the derby database and derby system. Then, with a different classloader, attempts to create the table if it doesn't exist, and inserts and entry (2), then shuts down the derby database and derby system. Then, as an additional experiment, it goes back to original classloader, attempts to create the table if it doesn't exist, and inserts and entry (3), then shut down the derby database and derby system.

Below is the output:

C:\tests>java TestDerbyInMemoryDatabase created new table inserted 1 contents of table: 1
Database 'memory:testdb' shutdown. Derby system shutdown.
created new table inserted 2 contents of table: 2
Database 'memory:testdb' shutdown. Derby system shutdown.
Table/View 'TBL1' already exists in Schema 'APP'. inserted 3 contents of table: 1 3
Database 'memory:testdb' shutdown. Derby system shutdown. T

The output seems to indicate that the in-memory database is tied in some way to the classloader from which the data source is loaded, as it appears that the classloaders each have their own memory:testdb database, each of which actually does survive the shutdown but is inaccessible to the data source loaded from the other class loader.


Reply via email to