Pergunta

Eu ter algo parecido com isto:

public static final String path;
static {
    path = loadProperties("config.conf").getProperty("path");
}

public static void main(String... args) {

    // ... do stuff (starting threads that reads the final path variable)

    // someone want's to update the path (in the config.conf file)
    restart(); // ???
}

Eu quero reinicializar a JVM chamar o inicializador estático novamente e, em seguida, main(...)!

Isso pode ser feito?

Foi útil?

Solução

Você pode iniciar seu aplicativo usando um personalizado carregador de classe, isto irá permitir que você carregar e descarregar as suas variáveis estáticas.

No entanto, basicamente, muito, muito, muito ruim design precisa fazer isso.Eu gosto de fazer campos de final, mas você não deve fazê-los final, se você deseja alterá-los.

Outras dicas

Se seu objetivo é simplesmente recarregar alguns arquivos de configuração, por que não implementar um monitor de alteração de arquivo?

Aqui está um bom tutorial sobre este assunto:

http://download.oracle.com/javase/tutorial/essential/io/notification.html

Eu acho que o que você está propondo (reiniciar seu aplicativo automaticamente) seria um pouco mais pesado do que apenas assistir a atualizações de arquivos.

Estou aceitando Peter Lawrey Responda, mas publique um exemplo completo para qualquer pessoa usar!

Não vou usar isso no código de produção ... Existem outras maneiras de fazê -lo!

public class Test {

    public static void main(String args[]) throws Exception {
        start();
        Thread.sleep(123);
        start();
    }

    private static void start() throws Exception {

        ClassLoader cl = new ClassLoader(null) {
            protected java.lang.Class<?> findClass(String name) 
            throws ClassNotFoundException {
                try{
                    String c = name.replace('.', File.separatorChar) +".class";
                    URL u = ClassLoader.getSystemResource(c);
                    String classPath = ((String) u.getFile()).substring(1);
                    File f = new File(classPath);

                    FileInputStream fis = new FileInputStream(f);
                    DataInputStream dis = new DataInputStream(fis);

                    byte buff[] = new byte[(int) f.length()];
                    dis.readFully(buff);
                    dis.close();

                    return defineClass(name, buff, 0, buff.length, null);

                } catch(Exception e){
                    throw new ClassNotFoundException(e.getMessage(), e);
                }
            }
        };

        Class<?> t = cl.loadClass("Test$Restartable");
        Object[] args = new Object[] { new String[0] };
        t.getMethod("main", new String[0].getClass()).invoke(null, args);
    }

    public static class Restartable {

        private static final long argument = System.currentTimeMillis();

        public static void main(String args[]) throws Exception {
            System.out.println(argument);
        }
    }
}

Uma abordagem mais simples é simplesmente não Para usar o inicializador estático para isso. Por que não apenas fazer path não final e carregue-o em main?

Que tal esta estrutura

public static void main(String... args) {

    boolean restart = true;
    while (restart )
    {
        retart = runApplication();
    }

}

Se você detectar a necessidade de reiniciar seu aplicativo, retorne a RunApplication true. Se for hora de sair, retorne false;

Se você possui uma interface do usuário ou um daemon para controlar a saída para o Stdout, pode fazer um invólucro do lado de fora que inicie seu programa.

Se o programa após saídas de saída "reiniciar", você poderá reiniciar seu programa novamente deste invólucro. Caso contrário, acaba.

Ou, se você quiser o caminho puro Java, pode seguir uma solução com carregadores de classe, como Peter Lawrey mencionou em seu cargo. Antes de seguir esse caminho, você realmente deve repensar seu design (se for o seu código) e tornar seu código capaz de se limpar.

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