Restart myself - can I reinitialize everything from scratch?

五迷三道 提交于 2019-12-20 02:56:10

问题


I have something like this:

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

I want to reinitialize the JVM calling the static initializer again, and then main(...)!

Can it be done?


回答1:


You can start your application using a custom class loader, this will allow you to load and unload your static variables.

However, basically its a very bad design to need to do this. I like making fields final, but you shouldn't make them final if you want to change them.




回答2:


If your goal is simply to reload some configuration files, why not implement a file change monitor?

Here's a good tutorial on this subject:

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

I think what you're proposing (restarting your application automatically) would be a little more cumbersome than just watching for file updates.




回答3:


I'm accepting Peter Lawrey answer but post a complete example for anyone to use!

I'm not going to use this in production code... there are other ways of doing it!

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



回答4:


A simpler approach is simply not to use the static initializer for this. Why not just make path non-final and load it in main?




回答5:


how about this structure

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

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

}

If you ever detect the need to restart you application, have runApplication return true. If it is time to exit return false;




回答6:


If you have an UI or a daemon so you can control output to stdout, you can make a wrapper on the outside that starts your program.

If the program upon exit outputs "RESTART" you can restart your program again from this wrapper. If not, it just ends.

Or if you want the pure java way, you can go with a solution with classloaders as Peter Lawrey mentioned in his post. Before going down this route you should really rethink your design (if it is your code) and make your code capable of cleaning itself up.



来源:https://stackoverflow.com/questions/4207593/restart-myself-can-i-reinitialize-everything-from-scratch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!