代码之家  ›  专栏  ›  技术社区  ›  dacwe

重新启动我自己-我可以重新初始化一切从头开始吗?

  •  2
  • dacwe  · 技术社区  · 14 年前

    我有这样的东西:

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

    我想重新初始化JVM,再次调用静态初始化器,然后 main(...) !

    能做到吗?

    6 回复  |  直到 14 年前
        1
  •  3
  •   Peter Lawrey    14 年前

    您可以使用自定义类加载器启动应用程序,这将允许您加载和卸载静态变量。

    然而,基本上这是一个非常糟糕的设计需要这样做。我喜欢将字段设置为final,但如果要更改字段,则不应将其设置为final。

        2
  •  2
  •   Jonathon Faust    14 年前

    如果您的目标只是重新加载一些配置文件,为什么不实现一个文件更改监视器?

    这里有一个关于这个主题的好教程:

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

    我认为你的建议(自动重启你的应用程序)将比仅仅监视文件更新要麻烦一些。

        3
  •  2
  •   Community Mofi    7 年前

    我接受 Peter Lawrey 回答,但张贴一个完整的例子供任何人使用!

    我不会在生产代码中使用这个。。。还有别的办法!

    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
  •  1
  •   Jon Skeet    14 年前

    更简单的方法是 为此使用静态初始值设定项。为什么不干脆 path 非最终版本并加载 main ?

        5
  •  0
  •   Aaron    14 年前

    这个结构怎么样

    public static void main(String... args) {
    
        boolean restart = true;
        while (restart )
        {
            retart = runApplication();
        }
    
    }
    

    如果检测到需要重新启动应用程序,请让runApplication返回true。 如果是退出假返回的时间;

        6
  •  0
  •   Knubo    14 年前

    如果您有一个UI或守护进程,以便可以控制stdout的输出,那么可以在外部创建一个包装器来启动程序。

    如果程序在退出时输出“重新启动”,您可以从这个包装器重新启动程序。如果没有,就结束了。

    或者如果你想要纯java的方式,你可以像Peter Lawrey在他的文章中提到的那样使用类加载器。在走这条路之前,你应该重新考虑你的设计(如果它是你的代码),并使你的代码能够自我清理。