2014-07-10 1 views
0

Je développe actuellement une application Java pour effectuer des calculs. Mon application va être distribuée sous forme de fichier jar et pour chaque calcul, je vais utiliser un script qui lance mon pot. Mon problème est le suivant: J'ai créé une classe singleton pour effectuer des interrogations de bases de données mais je ne sais pas comment réparer mon singleton dans la JVM entre deux exécutions de jar. J'ai essayé de lancer une classe vide en stockant le singleton et en attendant infiniment mais quand j'exécute mon programme jar le singleton n'est pas récupéré mais instancié ... Mon code est le suivant:Comment réparer un singleton dans une JVM?

Le programme principal pour garder le singleton dans la machine virtuelle Java:

/** 
* 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); 
     } 
    } 
} 

Mon 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; 
    } 
} 

j'étais certain que cela fonctionnerait ... pouvez-vous me expliquer pourquoi ce n'est pas? Merci pour l'aide :)

EDIT: J'ai vérifié le chargeur de classe et il est toujours le même (pour l'application de pot et le MainSingleton)

+1

Le Singleton est unique dans la JVM. Mais 2 jars exécutions = 2 JVM. Quel est votre besoin exactement? –

+0

"Lorsque j'exécute mon programme jar, le singleton n'est pas récupéré mais instancié" - Pouvez-vous clarifier ce que vous voulez dire? La question n'est pas claire pour moi. – Swapnil

+0

@ArnaudDenoyelle J'ai besoin de créer un pseudo service toujours en cours d'exécution dans la JVM et auquel mes programmes jar peuvent accéder. J'utilisais RMI auparavant mais mes programmes fonctionnaient localement donc j'ai essayé la solution singleton ... – Ko2r

Répondre

1

Un singleton est un modèle de conception qui garantit il n'y a qu'une seule instance d'une classe donnée DANS LA MÊME JVM *

Qu'est-ce que vous essayez de faire est de partager une instance singleton entre 2 différents JVMs (chaque processus java.exe est un jvm séparé). Tu ne peux pas le faire. Comme c'est le cas actuellement, chaque processus java (= jvm) va initialiser sa propre instance singleton @startup (et donc maintenir sa propre connexion).

Si vous n'êtes pas satisfait de ce que vous pourrait faire est de maintenir votre connexion db dans un 3ème, fond, processus (donc 3 jvm), et ont toutes les autres JVMs en cours d'exécution sur le même travail de la machine à travers ce (comme un proxy). Cela compliquerait grandement votre code et n'est probablement pas nécessaire.

* et même dans ce cas, il existe des scénarios impliquant des hiérarchies de chargeur de classe où cela casse.

+0

Mon mauvais je pensais que je pourrais partager ce singleton ... GRR Je vais chercher une autre façon d'avoir un service (peut-être revenir à RMI ...). Avez-vous une idée de la façon la plus simple de le faire? – Ko2r

+0

@ Ko2r - simple et RMI ne mélange généralement pas :-) Qu'est-ce qui est si mauvais d'avoir plusieurs connexions? – radai

+0

Mes connexions sont longues (je me connecte à HBase et MySQL, cela prend environ 5 secondes) et mon calcul doit être rapide, donc je dois créer un service pour interroger mes bases de données ... – Ko2r

0

Chaque fois que vous exécutez un pot avec java -jar ... une nouvelle machine virtuelle Java c'est commencé. Vous ne pouvez pas utiliser les objets d'une exécution précédente.