como eu faco pra o meu software soh abrir 1 vez?? tipo, qdo ele ja estiver aberto, c tenta abri ele d novo ele soh recebe focus (como o MSN)
Como impedir q o programa seja aberto + de 1 vez?
26 Respostas
Olá
Crie um ServerSocket com uma porta qualquer (diferente de zero) que seu programa tenha permissão de acessar. Na primeira vez funciona, nas demais dá IOException.
[]s
Luca
Meio gambiarra mas funciona 
Use arquivos com ou sem filelocking.
vc tb pode colocar um ponto na tela quando o programa abrir, dai se o programa abrir e ver q o ponto ta lá dai o programa naum abre. hehehehe
Pultz… a solução do Luca é muito boa! Vou me lembrar dela que, com certeza, um dia será útil!
é mas se por acaso a porta já estiver sendo usado por algum outro programa (o cara tb tem q ter muito azar heim)
n entendi…
Olá
Louds, se vc lembrar já discutimos longamente este tema e as possíveis desvantagens de usar arquivos. Só vou lembrar que no sistema em que usamos ServerSocket antes usávamos arquivos (sem java.nio e portanto sem locking) e deixamos de usar porque em caso de pane no sistema os arquivos davam encrenca. Com sockets nunca deu problema. Mas com java.nio seria possível adotar file locking.
[]s
Luca
Acho q ele quis dizer pra criar um arquivo e abri-lo com o programa, dai se o outra instância do programa tentar abrir o arquivo vai dizer que o arquivo está berto e vc pode tratar isso para naum abrir o programa.
Ou talvez para quando o programa for carregado ver no proprio programa para ver se ele está sendo usado, mas ai eu naum sei se sempre quando ele for abrir ele vai estar sendo usado(porq vai)
naum entendeu? vai comer uma pizza
Na verdade tanto arquivos (com filelocking) e sockets tem problemas.
Bloquear a execução caso a criação de um arquivo falhe pode dar problema se o teu programa travar e o arquivo não for apagado.
Usar filelocking tem o problema de que o arquivo pode ser recriado dependendo da plataforma e o locking ir pro vinagre. Com locking se o programa ou o sistema falharem o lock acaba.
ServerSockets tem o problema de port lingering, quando o SO não permite reutilizar por um período.
Ou seja, não existe opção portavel em java que seja 100%. Mas server sockets e filelocking resolvem na maioria dos casos.
Quem dera java tivesse suporte a primitivas de IPC, como named pipes/mutexes.
usa um Singleton para instanciar seu programa
O jeito mais confiável de fazer isso é seguir a sugestão do louds e ainda seguir um protocolo para verificar se o aplicativo está de pé. Por exemplo, a aplicação deveria escutar neste socket para mandar uma String de volta ao chamador que indica que ela está viva. Assim, caso não seja ela que esteja travando a porta, pode-se exibir uma mensagem mais clara para o usuário de que outra aplicação está utilizando a porta.
certo, vcs esclarecam a abordagem 1 q eu fiz, d travar a inicilizacao do programa, mas ng toco no assunte de:
o programa ja esta aberto? entao de foco nele!
nem sei c da pra faze isso :P, mas td bem, e tipo, alguem podia da um exemplo desse ai usando arquivo plz
vlw
Usa singleton ou então properties (menos confiável)
Olá
Wilker, se o programa já está aberto acho que não é possível passar o foco para ele. Provavelmente isto só funciona no Windows.
Da outra vez que defendi aqui a solução do ServerSocket fui obrigado a postar o trecho de código que usamos no Banco Postal para provar que é viável. Ainda bem que desta vez a turma aceitou mais facilmente. Wilker, dê uma pesquisada que vc acha o código.
Michael, dificilmente há a possibilidade de coincidência de portas. Mas pelo que sei Murphy ainda não morreu! Veja solução gambiarrativa no final desta mensagem.
A solução é um ServerSocket mas é claro que se pode também em caso de IOException, abrir um Socket cliente setando setSoLinger(false, 0) para checar se realmente é a nossa aplicação que detem a porta. Esta verificação não poderia ser feita com os lockings.
Louds, com ServerSocket não dá para setar o linger timeout. Então se não abrir o ServerSocket é porque realmente a porta está em uso e se está bloqueda pelo linger timeout, isto não foi feito por nossa aplicação. Para confirmar se é realmente nossa aplicação se pode abrir o Socket cliente para se comunicar com a outra instância.
A solução gambiarrativa depende de a cada falha na tentativa de abrir o ServerSocket, tentar abrir um Socket cliente e ver se abre comunicação com a outra instância de nossa aplicação. Caso se confirme a possibilidade de coincidência de portas pela falha da troca com o Socket cliente, se pode alterar um arquivo de configuração e gravar um número de porta para o qual se conseguiu abrir com sucesso. Ao começar a aplicação se obtem a porta neste arquivo de propriedades.
Grinvon, singleton não funciona porque um novo aplicativo usa uma outra JVM.
Finalmente java.nio.channels.Pipe não serve como alternativa ao ServerSocket porque só funciona na mesma JVM.
PS: linger timeout é o período que a conexão permanece aberta mesmo depois do socket fechado para garantir que todos os dados são transmitidos. Verifique isto com netstat -a
[]s
Luca
certo, vcs esclarecam a abordagem 1 q eu fiz, d travar a inicilizacao do programa, mas ng toco no assunte de:o programa ja esta aberto? entao de foco nele!
nem sei c da pra faze isso :P, mas td bem, e tipo, alguem podia da um exemplo desse ai usando arquivo plz
vlw
Com o ServerSocket dah pra pegar foco facim facim…
VELO
Singleton não evita que uma nova JVM seja iniciada com uma nova instância da sua aplicação 
A saída é fazer com que sua aplicação faça uso exclusivo de um recurso, como o Luca e o Louds falaram.
Louds, perguntinha: com aquela viagem do projeto Barcelona, vai ser possível criar aplicações exclusivas de maneira portável e não-escrota, não?
Daniel, se tiver algum mecanismo de comunicação inter-isolates, sem dúvida. Um IsolateSocket, por exemplo.
Luca, o linger que eu me referi é ao fato da operação de port binding ter um timeout de 120 segundos na maioria dos unix. Por isso que client sockets pegam uma porta disponivel qualquer.
Mas para o caso do Wilker, a solução do Luca, junto com a “gambiarra” que ele propos, é melhor. Uma vez que o aplicativo pode alem de abrir um server socket aceitar conexões para saber que tem que ganhar foco.
certo, vcs esclarecam a abordagem 1 q eu fiz, d travar a inicilizacao do programa, mas ng toco no assunte de:o programa ja esta aberto? entao de foco nele!
Simples. Se você seguiu minha sugestão do protocolo, depois que sua aplicação “provar” que é ela que está aberta, envie um outro comando via socket que seja interpretado como uma instrução para que a janela atual ganhe foco.
Desculpe entrar atrasado no ônibus e querer sentar na janelinha, mas não tem jeito de eu verificar se já existe uma instância do objeto na memória simplesmente? Se tiver como faço? Tipo tem como dar um “focus” no objeto que já está na memóira?
Ixi não dah pra fazer facilmente como se faz no windows, o jeito (pelo q li em outros forums) é usar Sockts, mas estava pensando em uma solução para o focus, cv, Luca e o pessoal mais fera em java, vejam se isto é viável:
Deixar uma porta de escuta no programa, aí se quando o programa for abrir novamente ele verifica se a porta estiver aberta, se estiver manda uma mensagem (ai naum sei o protocologo, pode ser UTB q é bem simples) para o programa, o programa interpreta a mensagem e dá foco em si mesmo, (acho q tem como dar foco no programa próprio neh?)
bom eu naum pude testar isso, mas talvez irá precisar usar duas porta, ou talvez apenas uma para “escutar”, dai se ela estiver sendo usada, usa a mesma porta para enviar a mensagem, sei lá pode ser…
Eu jah fiz isso. Funciona, na boa…
Não é dificil não… eu tenho até uma API que eu uso em uns 3 projetos meus q usam isso.
VELO
Identificar se uma instância já existe?
Primeiro você precisa definir o que é igualdade para seu objeto. nesse caso, igualdade não é a mesma posição em memória, então procure sobrescrever o método equals.
Depois, você vai ter que ter um objeto que faz essa pesquisa. Uma Factory pode receber parâmetros e checar se um objeto com estes parâmetros já existe antes de criá-lo, mantendo uma rafer~encia á eles. Tipo:
class FactoryABC{
static Map isntancias = new HashMap();
public MeuObjeto criar(int parametroQualquer){
if(! instancias.containsKey(parametroQualquer) ) {
ualquer);
instancias.put(parametroQualquer, novo);
}
return instancias.get(parametroQualquer);
}
}
Estava com esse problema hoje pela manha e consegui resolve-lo de uma forma q não sei se eh tão segura e eficiente…
usei o metodo do arquivo. Sempre q o programa for iniciado ele cria uma “trava”(arquivo) e sempre q fechado a trava é destruida. O problema como eu li aqui é que caso haja um KILL a trava nunca sera destruida e o programa nunca sera executado novamente acusando que já tem um em execução mas…
Usei o addShutdownHook do Runtime pra assim que a JVM for encerrada a trava ser destruida tambem. Ate agora funcionou sem problemas não fiz muitos testes. Será que dessa forma há alguma coisa que bugue muito?
valeu ae 
Não porque ao iniciar uma nova copia do programa uma nova JVM será aberta. E ai a memoria de uma não tem acesso à da outra. Se vc se refere à memoria da máquina , vc teria que implementar algo via JNI para isso e brincar com a memória é sempre ruim. Vc tb poderia fazer as memorias comunicarem, mas ai vc cai no mecanismo de sockets.
Olá
Neste e em outros tópicos já foi explicado porque a complexa solução de travar um arquivo não é adequada e porque a solução simples de abrir um socket funciona a contento. O código já foi até publicado em mais de um tópico.
[]s
Luca