10

使用 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>

编辑/跟进:根据这篇文章和这篇文章,似乎不可能为可执行 JAR 指定 JVM 参数。

4

5 回答 5

5

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

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

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

于 2008-10-12T02:34:04.770 回答
3

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

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

概述:

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

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

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

  4. 等待子进程完成

这是一篇很好的背景文章

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
于 2008-10-12T18:20:58.977 回答
0

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

于 2013-06-05T16:57:33.120 回答
0

如果你这样想的话,我认为这是可以做到的。生成一个.bat包含命令的文件:

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

您可以尝试查看这个适用于 maven 的应用程序汇编器插件

我试过了,似乎有效。我仍然不清楚如何使用略有不同的内容生成 .bat 文件,但我认为这是可行的。

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

于 2018-04-16T21:31:43.993 回答
-2

古老的问题,但在我的谷歌搜索中出现了这个确切的问题,所以我正在回答它。

尝试

<configuation>
...
<argLine> -Xmx500m </argLine>
...
</configuation>
于 2011-10-21T10:16:52.167 回答