如何替换当前的Java进程,如unix风格的exec?

如何替换当前的Java进程,如unix风格的exec?,java,windows-services,Java,Windows Services,我有一个用Java编写的服务器,它作为Windows服务运行(多亏了Install4J)。我希望这个服务能够下载它运行的JAR文件的最新版本,并开始运行新代码。关键是我不希望Windows服务完全退出 理想情况下,我可以通过一个unix风格的exec()调用来停止当前版本并运行新版本来实现这一点。如何才能最好地实现这一点?据我所知,在Java中无法做到这一点 我想您可以通过使用Java或的start()命令(启动新进程)来解决这个问题,然后让当前的一端。。。文件状态 在以下情况下不会终止子进程:

我有一个用Java编写的服务器,它作为Windows服务运行(多亏了Install4J)。我希望这个服务能够下载它运行的JAR文件的最新版本,并开始运行新代码。关键是我不希望Windows服务完全退出


理想情况下,我可以通过一个unix风格的exec()调用来停止当前版本并运行新版本来实现这一点。如何才能最好地实现这一点?

据我所知,在Java中无法做到这一点

我想您可以通过使用Java或的start()命令(启动新进程)来解决这个问题,然后让当前的一端。。。文件状态

在以下情况下不会终止子进程: 没有更多的参考文献 进程对象,而不是 子进程继续执行 异步的

我假设如果父对象完成并被垃圾收集,情况也是如此

捕获是运行时。exec的进程将不再具有有效的输入、输出和错误流。

常规方法:

import java.io.BufferedInputStream;
import java.util.Arrays;

public class ProcessSpawner {    
public static void main(String[] args) {
    //You can change env variables and working directory, and
    //have better control over arguments.
    //See [ProcessBuilder javadocs][1]
    ProcessBuilder builder = new ProcessBuilder("ls", "-l");

    try {
        Process p = builder.start();
        //here we just echo stdout from the process to java's stdout.
        //of course, this might not be what you're after.
        BufferedInputStream stream = 
            new BufferedInputStream(p.getInputStream());
        byte[] b = new byte[80];
        while(stream.available() > 0) {                 
            stream.read(b);
            String s = new String(b);
            System.out.print(s);
            Arrays.fill(b, (byte)0);
        }
        //exit with the exit code of the spawned process.
        System.exit(p.waitFor());

    } catch(Exception e) {
        System.err.println("Exception: "+e.getMessage());
        System.exit(1);
    }
  }
}

这是一种复杂但便携的方法

将代码拆分为两个jar。有一个非常小的jar用于管理流程启动。它创建一个类加载器,将另一个jar保存在它的类路径上

当您想要加载一个新版本时,终止所有运行旧jar代码的线程。从旧jar中删除对类实例的所有引用。清空对加载旧jar的类加载器的所有引用。此时,如果没有遗漏任何内容,则旧类和类加载器应该可以进行垃圾收集


现在,您可以使用指向新jar的新类加载器实例重新开始,并重新启动应用程序代码。

您可以使用内置的重新加载功能,例如Tomcat、Jetty或JBoss,它们可以作为服务运行,而不必将它们用作web容器或Java EE容器

其他选项包括OSGi和您自己的类加载功能

但是要注意在生产环境中重新加载。这并不总是最好的解决方案。

可以做到这一点,甚至更多