Pergunta

Tenho um aplicativo Java que inicia outro aplicativo Java.O iniciador possui um temporizador de watchdog e recebe notificações periódicas da segunda VM.No entanto, se nenhuma notificação for recebida, a segunda máquina virtual deverá ser encerrada e o inicializador executará algumas atividades de limpeza adicionais.

A questão é: existe alguma maneira de fazer isso usando apenas java?até agora tenho que usar alguns métodos nativos para realizar esta operação e é um tanto feio.

Obrigado!

Foi útil?

Solução

Posso estar faltando alguma coisa, mas você não pode ligar para o destroy() método no Process objeto retornado por Runtime.exec()?

Outras dicas

Você pode usar java.lang.Process para fazer o que quiser.Depois de criar o processo aninhado e ter uma referência à instância do Processo, você poderá obter referências aos seus fluxos de saída e erro padrão.Você pode monitorá-los periodicamente e chamar .destroy() se quiser encerrar o processo.A coisa toda pode ser mais ou menos assim:

Process nestedProcess = new ProcessBuilder("java mysubprocess").start();
InputStream nestedStdOut = nestedProcess.getInputStream(); //kinda backwards, I know
InputStream nestedStdErr = nestedProcess.getErrorStream();
while (true) {
    /*
       TODO: read from the std out or std err (or get notifications some other way)
       Then put the real "kill-me" logic here instead of if (false)
    */
    if (false) {
        nestedProcess.destroy();
        //perform post-destruction cleanup here
        return;
    }

    Thread.currentThread().sleep(1000L); //wait for a bit
}

Espero que isto ajude,

Sean

Você também pode publicar um serviço (via serapilheira, hessian, etc) na segunda JVM que chama System.exit() e consumi-lo da JVM watchdog.Se você desejar apenas encerrar a segunda JVM quando ela parar de enviar essas notificações periódicas, ela poderá não estar em condições de responder à chamada de serviço.

Chamar comandos shell com java.lang.Runtime.exec() é provavelmente sua melhor aposta.

A maneira usual de fazer isso é chamar Process.destroy()...no entanto, é uma solução incompleta, pois ao usar a JVM sun em *nix destroy mapeia para um SIGTERM que não garante o encerramento do processo (para isso você também precisa do SIGKILL).O resultado líquido é que você não pode fazer gerenciamento de processos reais usando Java.

Existem alguns bugs abertos sobre esse problema, consulte:Texto do link

java.lang.Process tem um método waitFor() para aguardar a morte de um processo e um método destroy() para encerrar o subprocesso.

OK, a reviravolta da essência é a seguinte:

Eu estava usando a API Process para fechar a segunda máquina virtual, mas não funcionou.

O motivo é que meu segundo aplicativo é um aplicativo Eclipse RCP e eu o iniciei usando o inicializador eclipse.exe incluído.

No entanto, isso significa que o método destroy() da API do processo terá como alvo o processo eclipse.exe.Eliminar esse processo deixa o processo Java ileso.Então, um dos meus colegas aqui escreveu um pequeno aplicativo que eliminará o aplicativo certo.

Portanto, uma das soluções para usar a API de processo (e remover etapas intermediárias redundantes) é usar o inicializador Eclipse, fazendo com que minha primeira máquina virtual duplique todas as suas funcionalidades.

Acho que terei que trabalhar.

Você deve ser capaz de executar os comandos java.lang.Runtime.exec e shell.

Você pode fazer com que o código java detecte a plataforma em tempo de execução e acione o comando kill process da plataforma.Este é realmente um refinamento em sua solução atual.

Há também Processo.destruir(), se você estiver usando o Construtor de Processos API

Não é exatamente gerenciamento de processos, mas você pode iniciar um servidor rmi na máquina virtual java que está iniciando e vincular um controlo remoto instância com um método que faz qualquer limpeza necessária e chama System.exit().A primeira VM poderia então chamar esse método remoto para desligar a segunda VM.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top