1. Introduction
In this tutorial, we’ll learn how to configure the heap size when we start a Spring Boot application. We’ll be configuring the -Xms and -Xmx settings, which correspond to starting and maximum heap size.
Then, we’ll use Maven first to configure the heap size when starting the application using mvn on the command-line. We’ll also look at how we can set those values using the Maven plugin. Next, we’ll package our application into a jar file and run it with JVM parameters provided to the java -jar command.
Finally, we’ll create a .conf file that sets JAVA_OPTS and run our application as a service using the Linux System V Init technique.
2. Running from Maven
2.1. Passing JVM Parameters
Let’s start by creating a simple REST controller that returns some basic memory information that we can use for verifying our settings:
@GetMapping("memory-status")
public MemoryStats getMemoryStatistics() {
MemoryStats stats = new MemoryStats();
stats.setHeapSize(Runtime.getRuntime().totalMemory());
stats.setHeapMaxSize(Runtime.getRuntime().maxMemory());
stats.setHeapFreeSize(Runtime.getRuntime().freeMemory());
return stats;
}
Let’s run it as-is using mvn spring-boot:run to get a baseline. Once our application starts, we can use curl to call our REST controller:
curl http://localhost:8080/memory-status
Our results will vary depending on our machine, but will look something like this:
{"heapSize":333447168,"heapMaxSize":5316280320,"heapFreeSize":271148080}
For Spring Boot 2.x, we can pass arguments to our application using -Dspring-boot.run.
Let’s pass starting and maximum heap size to our application with -Dspring-boot.run.jvmArguments:
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Xms2048m -Xmx4096m"
Now, when we hit our endpoint, we should see our specified heap settings:
{"heapSize":2147483648,"heapMaxSize":4294967296,"heapFreeSize":2042379008}
2.2. Using the Maven Plugin
We can avoid having to provide parameters each time we run our application by configuring the spring-boot-maven-plugin in our pom.xml file:
Let’s configure the plugin to set our desired heap sizes:
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<configuration>
<mainClass>com.baeldung.heap.HeapSizeDemoApplication</mainClass>
</configuration>
</execution>
</executions>
<configuration>
<executable>true</executable>
<jvmArguments>
-Xms256m
-Xmx1g
</jvmArguments>
</configuration>
</plugin>
</plugins>
Now, we can run our application using just mvn spring-boot:run and see our specified JVM arguments in use when we ping our endpoint:
{"heapSize":259588096,"heapMaxSize":1037959168,"heapFreeSize":226205152}
Any JVM arguments we configure in our plugin will take precedence over any supplied when running from Maven using -Dspring-boot.run.jvmArguments.
3. Running with java -jar
If we’re running our application from a jar file, we can provide JVM arguments to the java command.
First, we must specify the packaging as jar in our Maven file:
<packaging>jar</packaging>
Then, we can package our application into a jar file:
mvn clean package
Now that we have our jar file, we can run it with java -jar and override the heap configuration:
java -Xms512m -Xmx1024m -jar target/spring-boot-runtime-2.jar
Let’s curl our endpoint to check the memory values:
{"heapSize":536870912,"heapMaxSize":1073741824,"heapFreeSize":491597032}
4. Using a .conf File
Finally, we’ll learn how to use a .conf file to set our heap size on an application run as a Linux service.
Let’s start by creating a file with the same name as our application jar file and the .conf extension: spring-boot-runtime-2.conf.
We can place this in a folder under resources for now and add our heap configuration to JAVA_OPTS:
JAVA_OPTS="-Xms512m -Xmx1024m"
Next, we’re going to modify our Maven build to copy the spring-boot-runtime-2.conf file into our target folder next to our jar file:
<build>
<finalName>${project.artifactId}</finalName>
<resources>
<resource>
<directory>src/main/resources/heap</directory>
<targetPath>${project.build.directory}</targetPath>
<filtering>true</filtering>
<includes>
<include>${project.name}.conf</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<configuration>
<mainClass>com.baeldung.heap.HeapSizeDemoApplication</mainClass>
</configuration>
</execution>
</executions>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
We also need to set executable to true to run our application as a service.
We can package our jar file and copy our .conf file over using Maven:
mvn clean package spring-boot:repackage
Let’s create our init.d service:
sudo ln -s /path/to/spring-boot-runtime-2.jar /etc/init.d/spring-boot-runtime-2
Now, let’s start our application:
sudo /etc/init.d/spring-boot-runtime-2 start
Then, when we hit our endpoint, we should see that our JAVA_OPT values specified in the .conf file are respected:
{"heapSize":538968064,"heapMaxSize":1073741824,"heapFreeSize":445879544}
5. Conclusion
In this short tutorial, we examined how to override the Java heap settings for three common ways of running Spring Boot applications. We started with Maven, both modifying the values at the command line and also by setting them in the Spring Boot Maven plugin.
Next, we ran our application jar file using java -jar and passing in JVM arguments.
Finally, we looked at one possible production level solution by setting a .conf file alongside our fat jar and creating a System V init service for running our application.
There are other solutions for creating services and daemons out of a Spring Boot fat jar, and many provide specific ways of overriding JVM arguments.
As always, the example code is available over on GitHub.