views:

4491

answers:

2

When using Maven to build an executable JAR, how do I specify the JVM arguments that are used when the JAR is executed?

I can specify the main class using <mainClass>. I suspect there's a similar attribute for JVM arguments. Specially I need to specify the maximum memory (example -Xmx500m).

Here's my assembly plugin:

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

Edit/Follow-up: It seems that it might not be possible to specify JVM arguments for an executable JAR according to this and this post.

+4  A: 

I don't know of any such mechanism. The JVM configuration is specified by the calling java command.

Here's the jar file specification which conspicuously doesn't mention any attribute other than Main-Class for stand-alone execution:

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

Alex Miller
+2  A: 

First off, let me say that anything this tricky is probably hard for a reason.

This approach that may work for you if you really need it. As written, it assumes "java" is on the caller's path.

Overview:

  1. Declare a Bootstrapper class as the main class in the jar's manifest.

  2. The bootstrapper spawns another process in which we call java (passing in any command-line arguments you want) on the "real" main class.

  3. Redirect the child processes System.out and System.err to the bootstrapper's respective streams

  4. Wait for the child process to finish

Here's a good background article.

src/main/java/scratch/Bootstrap.java - this class is defined in pom.xml as the jar's mainclass: <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 - this is the normal entry point for your program

package scratch;

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

Calling: java -jar scratch-1.0-SNAPSHOT-jar-with-dependencies.jar Returns:

Hello World! maxMemory:520290304
Exit:0
David Carlson