如何为Maven构建可执行JAR指定JVM参数

时间:2008-10-11 00:43:43

标签: java maven-2 jar executable-jar

使用Maven构建可执行JAR时,如何指定执行JAR时使用的JVM参数?

我可以使用<mainClass>指定主类。我怀疑JVM参数有类似的属性。特别需要指定最大内存(例如-Xmx500m)。

这是我的程序集插件:

  <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <mainClass>com.me.myApplication</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>

编辑/跟进:似乎可能无法根据thisthis帖子为可执行JAR指定JVM参数。

5 个答案:

答案 0 :(得分:4)

我不知道任何这样的机制。 JVM配置由调用java命令指定。

这是jar文件规范,显然没有提到Main-Class以外的任何属性用于独立执行:

http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html

答案 1 :(得分:2)

首先,让我说任何这个棘手的事情都可能是有原因的。

如果您确实需要,这种方法可能对您有用。如上所述,它假设“java”在调用者的路径上。

概述:

  1. 将jarstrapper类声明为jar清单中的主类。

  2. 引导程序产生另一个进程,我们在“真正的”主类上调用java(传入你想要的任何命令行参数)。

  3. 将子进程重定向System.out和System.err到引导程序的各个流

  4. 等待子进程完成

  5. 这是good background article

    src / main / java / scratch / Bootstrap.java - 此类在pom.xml中定义为 jar的主类:<mainClass>scratch.Bootstrap</mainClass>

    package scratch;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.PrintStream;
    
    public class Bootstrap {
        class StreamProxy extends Thread {
            final InputStream is;
            final PrintStream os;
    
            StreamProxy(InputStream is, PrintStream os) {
                this.is = is;
                this.os = os;
            }
    
            public void run() {
                try {
                    InputStreamReader isr = new InputStreamReader(is);
                    BufferedReader br = new BufferedReader(isr);
                    String line = null;
                    while ((line = br.readLine()) != null) {
                        os.println(line);
                    }
                } catch (IOException ex) {
                    throw new RuntimeException(ex.getMessage(), ex);
                }
            }
        }
    
        private void go(){
            try {
                /*
                 * Spin up a separate java process calling a non-default Main class in your Jar.  
                 */
                Process process = Runtime.getRuntime().exec("java -cp scratch-1.0-SNAPSHOT-jar-with-dependencies.jar -Xmx500m scratch.App");
    
                /*
                 * Proxy the System.out and System.err from the spawned process back to the user's window.  This
                 * is important or the spawned process could block.
                 */
                StreamProxy errorStreamProxy = new StreamProxy(process.getErrorStream(), System.err);
                StreamProxy outStreamProxy = new StreamProxy(process.getInputStream(), System.out);
    
                errorStreamProxy.start();
                outStreamProxy.start();
    
                System.out.println("Exit:" + process.waitFor());
            } catch (Exception ex) {
                System.out.println("There was a problem execting the program.  Details:");
                ex.printStackTrace(System.err);
    
                if(null != process){
                    try{
                        process.destroy();
                    } catch (Exception e){
                        System.err.println("Error destroying process: "+e.getMessage());
                    }
                }
            }
        }
    
        public static void main(String[] args) {
            new Bootstrap().go();
        }
    
    }
    

    src / main / java / scratch / App.java - 这是您程序的正常入口点

    package scratch;
    
    public class App 
    {
        public static void main( String[] args )
        {
            System.out.println( "Hello World! maxMemory:"+Runtime.getRuntime().maxMemory() );
        }
    }
    

    致电:java -jar scratch-1.0-SNAPSHOT-jar-with-dependencies.jar 返回:

    Hello World! maxMemory:520290304
    Exit:0
    

答案 2 :(得分:0)

回应David Carlson的回答,你可以通过使用java.home系统属性找到java可执行文件而不是依赖用户的路径来查找它,从而减少它的脆弱性。此外,您可能应该将标准输入重定向到子进程。

答案 3 :(得分:0)

我认为如果你这样想的话就可以做到这一点。 生成一个具有命令的.bat文件:

> java .. yourClass.. -D<jvmOption1> -D<jvmOption2>...

您可以尝试查看此app assembler plugin以获取maven。

我试了一下,似乎工作了。我仍然不清楚如何使用稍微不同的内容生成.bat文件,但我认为它是可行的。

作为另一种选择,您可能总是尝试在项目的资源子文件夹中创建.bat文件,并在您的发行版中包含该子文件夹。

答案 4 :(得分:-1)

古老的问题,但我在Google上搜索了这个确切的问题,所以我正在回答它。

尝试

<configuation>
...
<argLine> -Xmx500m </argLine>
...
</configuation>