Ko2r
Ko2r

Reputation: 1631

How to fix a singleton in a JVM?

I'm currently developing a Java application for performing calculus. My application is going to be distributed as a jar file and for each calculus I'll have to perform I'll use a script launching my jar. My problem is the following : I've created a singleton class for performing database interrogations but I don't know how to fix my singleton in the JVM between two jar executions. I've tried to launch an empty class storing the singleton and then waiting infinitely but when I'm executing my jar program the singleton is not retrieved but instantiated ... My code is the following :

The main program for keep the singleton in the JVM :

/**
 * Entry point for the singleton generation
 * @author yann.blanc
 *
 */
public class MainSingleton {
    /**
     * Entry point
     * @param args Command line arguments, used to define the request type
     */
    public static void main (String[] args) {
        try {
            /*Here my singleton is instantiated*/
            DatabaseServiceSingleton service = DatabaseServiceSingleton.getInstance();
            while (true)
            {
                Thread.sleep(1000);
            }
        } catch (ServiceException e) {
            e.printStackTrace();
            System.exit(0);
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.exit(0);
        }
    }
}

My singleton :

public final class DatabaseServiceSingleton implements IDatabaseService {

    private static DatabaseServiceSingleton instance = null;

    /*PARAM and FUNCTIONS OMIT FOR A BETTER READABILITY*/

    /*Constructor with exception to ensure that clients are stopped if the singleton can't be instantiated*/
    private DatabaseServiceSingleton() throws ServiceException {
        try {
            /*Get the current path*/
            String urlCourante = getClass().getProtectionDomain().getCodeSource().getLocation().getFile();
            String[] tab;
            if(urlCourante.contains("\\")){
                tab = urlCourante.split("\\");  
            } else {
                tab = urlCourante.split("/");   
            }
            for(int i = 0; i < tab.length -1; i++) {
                pathFolder += tab[i];
            }
            /*Get configuration informations*/
            getConfiguration();
            /*Init database connectors*/
            initBaseConnexion();
            System.out.println(this.getClass().getClassLoader().toString());
        } catch (Exception e) {
            throw new ServiceException("Problème d'entrée sortie lors de la lecture du fichier "
                    + "de configuration. Le service n'a pas pu être instancié : "+e.getMessage());
        }
    }

    /*Method for retrieve the singleton instance*/
    public static synchronized DatabaseServiceSingleton getInstance() throws ServiceException {
        if (instance == null) {
            instance = new DatabaseServiceSingleton();
        }
        return instance;
    }
}

I was certain that it would work ... can you explain me why it's not ? Thank you for the help :)

EDIT : I've checked the class loader and it's always the same (for the jar application and the MainSingleton)

Upvotes: 0

Views: 221

Answers (2)

radai
radai

Reputation: 24202

A singleton is a design pattern that guarantees there is only a single instance of a given class WITHIN THE SAME JVM*

What you're trying to do is share a singleton instance between 2 different jvms (each java.exe process is a separate jvm). You can't do it. As it is right now, each java process (==jvm) will initialize its own singleton instance @startup (and hence maintain its own connection).

If you're unhappy with this what you could do is maintain your db connection in a 3rd, background, process (hence 3rd jvm), and have all other jvms running on the same machine work through this (like a proxy). This would greatly complicate your code and is probably not needed.

*and even then, there are scenarios involving class loader hierarchies where that breaks.

Upvotes: 1

Henry
Henry

Reputation: 43788

Each time you run a jar with java -jar ... a new JVM ist started. You cannot use objects from a previous run.

Upvotes: 0

Related Questions