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

时间:2008-10-13 16:09:21

标签: java windows-services

我有一个用Java编写的服务器作为Windows服务运行(感谢Install4J)。我希望此服务能够下载其运行的最新版本的JAR文件,并开始运行新代码。缝合是我不希望Windows服务完全退出。

理想情况下,我会通过unix样式的exec()调用来完成此操作,以停止当前版本并运行新版本。我怎样才能做到最好?

5 个答案:

答案 0 :(得分:1)

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

我想你可以通过使用Java Runtime.execProcessBuilder的start()命令(启动新进程)来解决它,然后让当前结束...文档状态< / p>

  

子进程未被杀死   没有更多的参考   过程对象,而不是   子进程继续执行   异步。

如果父母完成并且是垃圾收集,我假设情况也一样。

捕获的是Runtime.exec的进程将不再具有有效的输入,输出和错误流。

答案 1 :(得分:1)

这是一种复杂但便携的方式。

将代码拆分为两个罐子。一个非常小的jar就是为了管理流程启动。它创建一个ClassLoader,在其类路径中保存另一个jar。

如果要加载新版本,可以终止从旧jar运行代码的所有线程。从旧jar中取消对类实例的所有引用。取消对加载旧jar的ClassLoader的所有引用。此时,如果您没有遗漏任何内容,旧类和ClassLoader应该有资格进行垃圾回收。

现在重新开始使用指向新jar的新ClassLoader实例,然后重新启动应用程序代码。

答案 2 :(得分:1)

Java Service Wrapper执行此操作以及更多内容。

答案 3 :(得分:0)

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

其他选项是OSGi,以及您自己的类加载功能。

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

答案 4 :(得分:-2)

一般方法:

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