Search code examples
spring-bootjpamemory-leaks

Spring Boot with JPA increasing memory usage


I am running tutorial code for JPA with Spring Boot web app.

My POM is

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>xxx</modelVersion>
<groupId>xxxx</groupId>
<artifactId>xxx</artifactId>
<version>xxx</version>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
    <relativePath />
</parent>

<properties>
    <start-class>com.Main</start-class>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.microsoft.sqlserver/mssql-jdbc -->

    <dependency>
        <groupId>javax.inject</groupId>
        <artifactId>javax.inject</artifactId>
        <version>1</version>
    </dependency>
    <dependency>
        <groupId>javax.persistence</groupId>
        <artifactId>javax.persistence-api</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>eclipselink</artifactId>
        <version>2.6.3</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.microsoft.sqlserver</groupId>
        <artifactId>mssql-jdbc</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
I am persisting only one class:
@Entity
@JsonInclude(Include.NON_NULL)
public class TransactionData {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(unique=true)
private String referenceId;

public String getReferenceId() {
    return referenceId;
}

public void setReferenceId(String referenceId) {
    this.referenceId = referenceId;
}

My application properties are:

spring.datasource.url= jdbc:sqlserver://xxx.xxx.xxx.xxx:xxxx;databaseName=xxxxxx
spring.datasource.username= xxx
spring.datasource.password= xxx
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServerDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update

Rest controller:

@Autowired
TDataService tDataService;

@RequestMapping("/initTx")
@ResponseBody
public String initTx(String atmId, String refId) {
    TransactionData tD=new TransactionData();
    tD.setReferenceId(refId);
    return tDataService.save(tD).getReferenceId();
}

Service:

@Autowired
TDataRepo repository;

public TransactionData save(TransactionData tData) {
    return repository.save(tData);
}

Repository:

public interface TDataRepo  extends JpaRepository<TransactionData, Long> 

Repository implements save method as provided in JpaRepository without modifications.

Once I start tomcat with web app, I am performing simple load stress test. I`m running 1000 rest calls to the controller, creating 1 insert to the dB at a time. There is 1sec delay between calls.

During the test, RAM is constantly increasing, which is expected, but it is never released. I am not sending any requests to the web controller after these 1k inserts are done, but ram remains the same, never dropping down to original idle value.

Am I missing something crucial here?


Solution

  • I don't think there is a "memory leak" there. I think it is related to how memory is managed by the JVM. In short, it doesn't immediately return not used memory to the OS. You can find some hints here Does GC release back memory to OS?