Executar apenas 1 instância de programa

Boa tarde.

Tenho uma dúvida meio básica mas, toda via, gostaria de implementar uma funcionalidade que não consegui…
No netbeans se você possuir uma instância dele em execução ele não abre uma nova da o foca na instância em execução. As vezes até exibe uma mensagem informando que possui uma instância em execução caso o windows tenha fechado incorretamente.

Não sei como fazer este controle, talvez possa fazer criando um arquivo, sei lá, mas existir uma forma de ler da máquina virtual e saber se existe uma instância de um jar em execução.

Pensei também em utilizar uma variável estática, e ai vem outra dúvida, tinha a idéia que teria apenas uma por classe, mas parece que cada instância de um jar na máquina virtual possui as suas variáveis estáticas. Caso se abra um jar 2 vezes ele carrega duas vezes as classes na máquina virtual?

Não sei se ficou claro, mas não consegui encontrar nada a este respeito, desde já agradeço.
:slight_smile:

Tipo… variavel estatica é por classe e classe é por aplicação entao 2 aplicações rodando na jvm terão classes separadas logo as variaveis estaticas tb…

uma possibilidade é ao abrir uma instancia salvar em um arquivo fisico da maquina o endereço da instancia ai caso abra uma segunda ele verifica se ha uma instancia aberta pelo arquivo fisico havendo ele da da um up na intancia aberta e fecha a nova instancia…

acabei de ter essa idéia nao sei se é a mais adequada…

pois é
eu comentei acima esta possibilidade, mas deve ter como fazer via código. Mexi um pouco vi que tem uma classe ClassLoader, talvez dê para fazer.

O problema do arquivo é que se acontecer um problema e a aplicação for fechada de maneira inesperada, o arquivo vai ficar lá. Mas da para contornar isso também.
Mas é curiosidade mesmo :slight_smile:

[quote=Beavis_]pois é
eu comentei acima esta possibilidade, mas deve ter como fazer via código. Mexi um pouco vi que tem uma classe ClassLoader, talvez dê para fazer.

O problema do arquivo é que se acontecer um problema e a aplicação for fechada de maneira inesperada, o arquivo vai ficar lá. Mas da para contornar isso também.
Mas é curiosidade mesmo :)[/quote]
Acho que daria para:

  1. Ocupar alguma porta TCP ou UDP pré-definida quando o programa inicializar, e quem sabe até registrar essa porta no IANA, sendo que quando alguma outra instância tentar inicializar, não deverá conseguir ocupar a mesma porta e portanto não deverá conseguir prosseguir executando.
  2. Criar um arquivo em algum lugar pré-definido e fazer o programa reter o acesso a esse arquivo, não deixando que outro programa leia ou modifique tal arquivo, sendo que quando alguma outra instância tentar inicializar, não deverá conseguir obter acesso ao arquivo e portanto não deverá conseguir prosseguir executando.

Inté.

Ok. Estas duas opções irão resolver o problema.
Mas a título de curiosidade existe uma forma de buscar as classes e aplicações rodando na máquina virtual?

Boa Tarde,

Sou novo aqui… tambem estou precisando de uma dica para fazer esse controle.

Achei informações interessantes e podem ajudar neste link:

http://www.guj.com.br/posts/list/64278.java

Só analisei por cima e não testei ainda, mas achei interessante a idéia de controlar pelo PID, através de comparações em tempo de execução.

Vou implementar e depois reportarei os resultados aqui.

:slight_smile:

Implementei a solução (conforme disse na msg anterior),

Ficou assim:

O método main identifica o PID e ele é passado para o método rastreadorApp(int processPid), que retorna true ou false.


     public static void main(String[] args) throws SocketException, IOException {
        
        RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean();   
        final int runtimePid = Integer.parseInt(rt.getName().substring(0,rt.getName().indexOf("@")));   
        
        if (rastreadorApp(runtimePid)){

              // aqui inicia a aplicação

        }else{
              System.exit(0);
        }
     }

e o método rastreadorApp(int processPid) fica assim:



private static boolean rastreadorApp(int processPid) {
        MonitoredHost host;
        Set vms;
        try {
            host = MonitoredHost.getMonitoredHost(new HostIdentifier((String)null));
            vms = host.activeVms();
        } catch (java.net.URISyntaxException sx) {
            throw new InternalError(sx.getMessage());
        } catch (MonitorException mx) {
            throw new InternalError(mx.getMessage());
        }
        MonitoredVm mvm = null;
        String processName = null;
        try{
            mvm = host.getMonitoredVm(new VmIdentifier(String.valueOf(processPid)));
            processName = MonitoredVmUtil.commandLine(mvm);
            processName = processName.substring(processName.lastIndexOf("\\") + 1,processName.length());
            mvm.detach();
        } catch (Exception ex) {
            
        }
        for (Object vmid: vms) {
            if (vmid instanceof Integer) {
                int pid = ((Integer) vmid).intValue();
                String name = vmid.toString();
                try {
                     mvm = host.getMonitoredVm(new VmIdentifier(name));
                     name =  MonitoredVmUtil.commandLine(mvm);
                     name = name.substring(name.lastIndexOf("\\")+1,name.length());
                     mvm.detach();
                     if ((name.equalsIgnoreCase(processName)) && (processPid != pid))
                         return false;
                } catch (Exception x) {
                     // ignore
                }
            }
        }
        
        return true;
	}
	

Aqui rodou legal e resolveu meu problema.

É necessário um jar especifico (tools.jar) que tem 11MB… mas o cara que postou essa solução descompactou e pegou somente as classes necessarias e disponibilizou para download… estou anexando as classes em formato .zip e o .jar delas tambem.

Espero que seja util para mais alguem.

abraços.

1 curtida

Pergunta… não precisa ter JMX habilitado?

[]´s

É uma boa pergunta, eu confesso que sou novato e não entendo muito bem de JMX… posso ta falando besteira, mas creio no JDK já deve ter incluído/habilitado.

O fato é que só precisei adicionar no meu projeto o jar que foi anexo na minha mensagem anterior e funcionou.