2008-10-11 13 views
7

Lorsque vous utilisez Maven pour créer un fichier JAR exécutable, comment puis-je spécifier les arguments JVM utilisés lors de l'exécution du fichier JAR? Je peux spécifier la classe principale à l'aide de <mainClass>. Je soupçonne qu'il existe un attribut similaire pour les arguments JVM. Spécialement j'ai besoin de spécifier la mémoire maximum (exemple -Xmx500m).Comment spécifier un argument JVM pour un exécutable construit par Maven JAR

Voici mon plugin Assembly:

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

Modifier/Suivi: Il semble que cela pourrait ne pas être possible de spécifier des arguments de JVM pour un JAR exécutable selon this et this poste.

Répondre

4

Je ne connais aucun mécanisme de ce type. La configuration de la JVM est spécifiée par la commande java appelant.

est ici la spécification de fichier jar qui ne manifestement pas mention d'attribut tout autre que Main-Class pour l'exécution autonome:

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

2

Tout d'abord, permettez-moi de dire que tout ce délicat est probablement difficile pour une raison.

Cette approche peut fonctionner pour vous si vous en avez vraiment besoin. Comme écrit, il suppose que "java" est sur le chemin de l'appelant.

Vue d'ensemble:

  1. Déclarez une classe de Bootstrapper comme la classe principale dans le manifeste du pot. Le bootstrapper engendre un autre processus dans lequel nous appelons java (en passant les arguments de la ligne de commande de votre choix) sur la classe principale "real".

  2. Rediriger l'enfant traite System.out et System.err aux flux respectifs du BootStrapper

  3. Attendez que le processus enfant pour terminer

est ici un good background article.

src/main/java/scratch/Bootstrap.java - cette classe est définie dans pom.xml comme le MainClass du pot: <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 - c'est le point d'entrée normal pour votre programme

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

Hello World! maxMemory:520290304 
Exit:0 
+3

Cela ressemble vraiment plus à un hack fragile. Considérant que sur beaucoup, beaucoup de machines, java (.exe) n'est pas dans le PATH, ou celui dans le PATH n'est pas celui que l'appelant voudrait utiliser, je ne vois pas comment cela ne causerait pas plus de problèmes que résoudre. –

-1

Ancienne question, mais est venu sur ma recherche Google pour ce problème précis, donc je réponds.

Essayez

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

Si ce morceau de code XML est pour le plugin exec Maven, alors FYI ne résoudra pas le problème OT ... – DejanLekic

0

En réponse à la réponse de David Carlson, vous pouvez le rendre moins fragile en utilisant la propriété du système java.home pour localiser l'exécutable java au lieu de compter sur le chemin de l'utilisateur pour le trouver. En outre, vous devriez probablement rediriger l'entrée standard vers le processus fils.

Questions connexes