53

As we know that we can set -Xmx1024M in window->preferences->java->installed jres->edit->default vm arguments in eclipse. But when I package this project into a runnable jar file, how can I set the -Xmx1024M when running the jar via java -jar A.jar?

Thanks a lot!

Judking
  • 6,111
  • 11
  • 55
  • 84

5 Answers5

171

Unfortunately, existing answers are wrong in one crucial point.

-Xmx must be passed to the Java runtime environment, not to the executed jar.

Wrong:

java -jar JavaApplication.jar -Xmx1024m 

Correct:

java -Xmx1024m -jar JavaApplication.jar 

More specifically, the java launcher needs to be used as follows:

java [options] -jar file.jar [arguments]

  • [options] are passed to the Java runtime environment
  • [arguments] are passed to the main function

The -Xmx parameter belongs to the (nonstandard) JVM options, and--being an option--needs to be listed before -jar (or at least before file.jar). The JVM will not recognize an -Xmx argument passed to the main function as proposed in other answers.

Philipp Merkle
  • 2,555
  • 2
  • 11
  • 22
  • 5
    A pitfall for the unwary - not to be funny, but the `-Xmx` parameter syntax is case sensitive. I was beating my head against the wall trying to figure out why I couldn't get this to work by modifying shortcut target properties, and that was why. – PatentWookiee Aug 24 '18 at 19:23
  • I had tried both ways, and used jvsualvm to see the jvm args, it shows JVM arguments as -Xmx2048m in both cases. Any clue as to why this happens? – NiharGht Jul 09 '20 at 11:38
10

Three methods:

  • Command Line:
  • Instruct your users to run your application using "java -Xmx1024m -jar SampleJavaApp.jar"
  • Java Control Panel:
  • Instruct your users to dedicate more memory to java by default: Win7 guide
  • Restart your jar with the appropriate Xmx value.

The last option is "evil" but doesn't require any extra effort from your users. Here's a sample block of code:

public static void main(String[] args) throws IOException, URISyntaxException {
    String currentPath=SampleJavaApp.class
          .getProtectionDomain()
          .getCodeSource().getLocation()
          .toURI().getPath()
          .replace('/', File.separator.charAt(0)).substring(1);
    if(args.length==0 && Runtime.getRuntime().maxMemory()/1024/1024<980) {
        Runtime.getRuntime().exec("java -Xmx1024m -jar "+currentPath+" restart");
        return;
    }
}
DKATyler
  • 914
  • 10
  • 16
9

try java -Xmx1024m filename.

I found this on StackOverflow What does Java option -Xmx stand for? and use it when I start Netbeans for instance.

use it like this

java -Xmx1024m -jar JavaApplication.jar

info: -Xmxn Specify the maximum size, in bytes, of the memory allocation pool. This value must be a multiple of 1024 greater than 2MB. Append the letter k or K to indicate kilobytes, or m or M to indicate megabytes. The default value is 64MB. The upper limit for this value will be approximately 4000m on Solaris 7 and Solaris 8 SPARC platforms and 2000m on Solaris 2.6 and x86 platforms, minus overhead amounts.

Kuzeko
  • 1,545
  • 16
  • 39
Davy Cielen
  • 370
  • 2
  • 8
  • 6
    Please note that in your proposed solution `-Xmx1024m` is passed to the executed jar file, not to the JVM as intended. See my answer for details: http://stackoverflow.com/a/42207984/7492402 – Philipp Merkle Feb 13 '17 at 15:47
  • 8
    The answer above is wrong - all JVM arguments should be passed right after java: i.e. java -Xmx4G -Xms1G .... your_jar.jar – morgan_il Jul 04 '17 at 14:41
  • 2
    ABOVE IS WRONG SEE ANSWER BELOW by @PhilippMerkle – DanGordon May 23 '18 at 14:36
  • 1
    Man I do not get how google's algorithm works, but that fetched answer made me waste so much time – realUser404 Jun 14 '18 at 01:43
4

Correct way to set Xmx value for jar file at run time is:

java -Xmx512m -jar Application.jar 
0

user1361991 > I like your evil option but I cannot comment it since I am still a newbie here. Anyway, I thought it deserved a little enhancement since I find it lacks the stderr and stdout redirection.

String currentPath= MyClass.class
    .getProtectionDomain()
    .getCodeSource().getLocation()
    .toURI().getPath()
    .replace('/', File.separatorChar).substring(1) ;
if ( args.length == 0 && Runtime.getRuntime().maxMemory()<512*1024*1024) {
    Process p= Runtime.getRuntime().exec("java -jar -Xmx512M " + currentPath + " restart") ;
    new StreamGobbler(p.getInputStream()).start() ;
    new StreamGobbler(p.getErrorStream()).start() ;
    p.waitFor() ;
    return ;
}

and the StreamGobbler source (probably retrieved from somewhere on the Internet to be honest and modified a little, I can't remember):

public class StreamGobbler
    extends Thread
{
    public StreamGobbler( InputStream is )
    {
        this(is, System.out) ;
    }

    public StreamGobbler( InputStream is, PrintStream ps )
    {
        this.is= is ;
        this.ps= ps ;
    }
    private final InputStream is ;
    private final PrintStream ps ;

    @Override
    public void run()
    {
        try {
            InputStreamReader isr= new InputStreamReader(is) ;
            BufferedReader br= new BufferedReader(isr) ;
            for ( String line ; (line= br.readLine()) != null ; ) {
                ps.println(line) ;
            }
       }
       catch ( IOException ioe ) {
           ioe.printStackTrace() ;
       }
    }
}
  • what do you mean by "stderr and stdout redirection"? and what does stream gobbler do? – kc ochibili Apr 15 '17 at 21:25
  • Hello and sorry for the late answer. The "problem" I wanted to address with the original evil solution was that it was hiding the output of the program when it's originally launched from the terminal (you can't see a simple log or the stacktrace if there is a non caught exception for example). So I modified it to redirect the output from System.out and System.err from the relaunched JVM to the original one. The little drawback is that the original program has to wait for the second to end, so the first one won't release the RAM immediately. – user4599075 May 24 '17 at 15:58