【问题标题】:Running a jar from within another jar从另一个 jar 中运行一个 jar
【发布时间】:2012-11-12 21:21:33
【问题描述】:

为了清楚起见,在我赏金之前重写它:

我想做的是为已经以(可执行)jar 形式制作的程序制作引导加载程序。这个引导程序在其运行时将有三个简单的目标:

  1. 将目标程序的本地 xml 文件与服务器上托管的文件进行比较(以确保它们是相同的版本)

  2. 如果不是同一个版本,在线版本较新,请下载较新版本。

  3. 重写 xml 文件以反映此更改。

  4. 执行第二个 jar 文件(像启动可执行文件一样启动它)。

我遇到的问题是第 4 步。尽管查看了 UrlClassLoader 和其他库,但我发现自己很难找到一种可靠的方法从我的引导程序中启动 jar。

由于一些外部问题,JNLP / Web-start 不适用于这种情况。

TL;DR:我需要找到一种从 jar 中下载/启动 jar 的方法,以便在运行引导程序时更新程序。

谢谢!

【问题讨论】:

标签: java jar runnable auto-update bootstrapping


【解决方案1】:

Runtime.getRuntime().exec()

如果您的 MyApp.jar 有任何输出,这里有一些陷阱。

查看文档了解如何正确使用 exec...

http://docs.oracle.com/javase/6/docs/api/java/lang/Process.html

并查看这篇关于一些陷阱的 SO 帖子...

Java Runtime.exec()

【讨论】:

    【解决方案2】:

    当您说“执行新 jar”时,您的意思是启动一个独立的应用程序吗? 一种可能性是简单地从 Updater.jar 引导逻辑中执行一个新的 Java 进程,然后自行退出。

    【讨论】:

    • 第二个 jar 本身就是一个独立的应用程序(它是一个可运行的 jar,只需要一个更新程序,这是 updater.jar 的唯一目的我运行第二个 jar 并退出引导程序没有问题,但是我该怎么做呢?我知道 System.exit(0); 会杀死应用程序本身,但我不确定如何事先运行另一个?
    • 见吉姆的回答。问题是,当您退出引导过程时,您将失去原来的标准输入和标准输出通道。我用一个应用程序做了类似的事情,但我让两个进程都保持活跃。但引导进程除了读取应用程序进程的标准输出外,什么也不做,在它启动它并将其回显到它的标准输出之后。
    【解决方案3】:

    换句话说,您想实现可自我更新的应用程序。这是可能的,甚至没有那么困难。

    您的程序应设计为包含 2 个部分。加载器(和更新器)和业务逻辑。加载器应该使用单独的类加载器启动业务逻辑。您可以使用UrlClassLoader。加载程序将转到在线服务并检查版本。如果需要,它将创建URLConnection,下载新的jar 并将其存储在文件系统中的某个位置(例如,在用户主目录中)。然后它将使用已经提到的类加载器运行业务逻辑,该类加载器从刚刚下载的 jar 文件加载类。

    这实际上模仿了 JNLP 行为。

    【讨论】:

    • 您是否有一个实现此功能的示例,因为我很想看看它是否会提供使我的项目正常运行所需的功能。
    【解决方案4】:

    我讨厌不得不回答自己的问题,但在这种情况下,我觉得有必要这样做......

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.xpath.XPath;
    import javax.xml.xpath.XPathConstants;
    import javax.xml.xpath.XPathExpression;
    import javax.xml.xpath.XPathFactory;
    
    import org.apache.http.HttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.params.BasicHttpParams;
    import org.apache.http.params.HttpConnectionParams;
    import org.apache.http.params.HttpParams;
    
    import org.w3c.dom.Document;
    
    
    public class updater {
    public static void main(String[] args) throws IOException {
        try{
            DefaultHttpClient httpclient = ClientMaker();
            HttpGet get = new HttpGet("http://encorpops04:8080/Updater-test/Version.xml");
            HttpResponse response = httpclient.execute(get);
            InputStream in = response.getEntity().getContent();
    
            DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = domFactory.newDocumentBuilder();
            Document doc = builder.parse(in);
    
            //Parse the Xml.
            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();
            XPathExpression expr = xpath.compile("//version/number/text()");
            String result = (String) expr.evaluate(doc, XPathConstants.STRING);
            System.out.println(result);
    
            File f = new File(System.getProperty("user.dir")+ "\\Version.xml");
            in = new FileInputStream(f) ;
            doc = builder.parse(in);
            expr=xpath.compile("//version/number/text()");
            String result2 = (String) expr.evaluate(doc, XPathConstants.STRING);
            System.out.println(result2);
    
    
            if(Double.parseDouble(result2) < Double.parseDouble(result)){
                HttpGet get2 = new HttpGet("http://encorpops04:8080/Updater-test/MyOutput.jar"); 
                HttpResponse response2 = httpclient.execute(get2);
                InputStream in2 = response2.getEntity().getContent();
                File f2 = new File("MyOutput.jar");
                OutputStream fos = new FileOutputStream(f2);
                byte buf[] = new byte[1024];
                int len;
                while ((len = in2.read(buf)) > 0) {
                    fos.write(buf, 0, len);
                }
                fos.close();
                in.close();
            }
            System.out.println("cmd.exe /C  javaw -jar"  +System.getProperty("user.dir") + "\\MyOutput.jar");
            Process p = Runtime.getRuntime().exec("cmd.exe /C  javaw -jar "  +System.getProperty("user.dir") + "\\MyOutput.jar");
            p.waitFor();
            p.destroy();
        }catch(Exception e){ e.printStackTrace(); }
    
    
    }
    
    public static DefaultHttpClient ClientMaker() {
        int connectiontimeout = 30000; // 1 second int sockettimeout = 1000;
        HttpParams httpparameters = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(httpparameters,
                connectiontimeout);
        HttpConnectionParams.setSoTimeout(httpparameters, connectiontimeout);
        DefaultHttpClient httpclient = new DefaultHttpClient(httpparameters);
        return httpclient;
    }
    
    }
    

    Version.xml 如下所示:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <version>
        <number>1.0</number>
    </version>
    

    旁注-我没有自动更新 version.xml,您可以编辑其中的数字以匹配,或者只需拉出您检查的数字来替换它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-12
      • 2017-12-21
      • 1970-01-01
      • 1970-01-01
      • 2016-03-01
      • 1970-01-01
      • 2012-12-28
      • 1970-01-01
      相关资源
      最近更新 更多