简体   繁体   中英

Spring Boot using dramatically more memory on 64-bit JVM

When running the same Spring Boot application on a 64-bit JVM (vs 32-bit), the memory usage is dramatically higher.

For the sample Eureka application below, the 32-bit JVM uses about 100 MB of RAM, whereas the 64-bit JVM uses about 700 MB of RAM. Running multiple microservices on the same computer starts to be a problem.

Does anyone know what is causing this? And most importantly, how can we eliminate the excessive memory use?

The example below is a slimmed-down version of our Eurkea server but it is happening with all of our Spring Boot microservices.

The java source:

@SpringBootApplication
@EnableEurekaServer
public class Eureka_SpringMVC {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(Eureka_SpringMVC.class).headless(false).run(args);
  }

}

And the Maven pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>ca.twosd.tcms</groupId>
<artifactId>TCMS_Web_Eureka</artifactId>
<version>1.0.0</version>

<parent>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-parent</artifactId>
    <version>Camden.SR6</version>  <!-- Name of release train -->
</parent>

<dependencies>
    <dependency>
        <!-- Setup Spring Boot -->
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <!-- Setup Spring MVC & REST, use Embedded Tomcat -->
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <!-- Spring Cloud starter -->
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter</artifactId>
    </dependency>

    <dependency>
        <!-- Eureka for service registration -->
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
    </dependency>

</dependencies>

<properties>
    <start-class>ca.eurekatest.Eureka_SpringMVC</start-class>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

</project>

Thanks!

How much heap size a jvm uses does not only depend on the jvm version, but also on the machine that the jvm is running on. Alas I do not find the specifications for that.

I once ran into problems with java processes running in docker containers in kubernetes on Google Container Engine, that the jvms were grabbing up to 16GB of memory when running on a Google Compute Engine with 54GB RAM. This definitely is too much, when there are lots of containers running on that host.

The same program on a different local machine uses much less memory. To find out how much memory a java program by default uses on a machine run the following command:

java -XX:+PrintFlagsFinal -version | grep -i heapsize

On my machine with 16GB memory this prints:

    uintx ErgoHeapSizeLimit                         = 0                                   {product}
    uintx HeapSizePerGCThread                       = 87241520                            {product}
    uintx InitialHeapSize                          := 268435456                           {product}
    uintx LargePageHeapSizeThreshold                = 134217728                           {product}
    uintx MaxHeapSize                              := 4294967296                          {product}
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

So the JVM takes as a maximum the fourth of the available memory. Try this with the 32bit and 64bit versions and you probably will see the differences.

To prevent this excessive claim of memory, always start your jvm with at least the -Xmx argument, for example:

java -Xmx512m -XX:+PrintFlagsFinal -version | grep -i heapsize

that now shows:

    uintx ErgoHeapSizeLimit                         = 0                                   {product}
    uintx HeapSizePerGCThread                       = 87241520                            {product}
    uintx InitialHeapSize                          := 268435456                           {product}
    uintx LargePageHeapSizeThreshold                = 134217728                           {product}
    uintx MaxHeapSize                              := 536870912                           {product}
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

You see the difference in the MaxHeapSize value. More information about the java options can be found here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM