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

发布于 2024-10-03 17:06:41 字数 449 浏览 6 评论 0原文

我有这样的事情:

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(...)

可以做到吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

一百个冬季 2024-10-10 17:06:41

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

然而,基本上这是一个非常糟糕的设计,需要这样做。我喜欢将字段定为最终字段,但如果您想更改它们,则不应将它们定为最终字段。

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.

寒江雪… 2024-10-10 17:06:41

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

这是关于此主题的一个很好的教程:

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

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

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.

稍尽春風 2024-10-10 17:06:41

一种更简单的方法是不使用静态初始化器来实现此目的。为什么不直接将 path 设置为非最终路径并将其加载到 main 中?

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?

清风挽心 2024-10-10 17:06:41

我接受 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);
        }
    }
}

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);
        }
    }
}
一抹淡然 2024-10-10 17:06:41

这个结构怎么样?

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

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

}

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

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;

双马尾 2024-10-10 17:06:41

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文