How to delete the bloat from Spring Boot app to reduce memory footprint and startup time?

826 Views Asked by At

Even simple Spring Boot app jar contains lots of dependencies and functionality which never will be used by your app. All this stuff:

  • should be loaded and it takes its time

  • many of these classes should be instantiated, initialized and will consume the memory and resources.

It could be crucial for micro service architecture and cloud native apps where memory footprint could be a price (e.g. https://run.pivotal.io/pricing/) and/or startup time is important.

E.g. the spring-boot-autoconfigure-2.1.6.RELEASE.jar (1.2Mb) contains couchbase, freemaker, cassandra and many others which with 99% probability never be used for your particular project. Or spring-core-5.1.8.RELEASE.jar (1.2Mb) contains the classes like KotlinDetector. Seriously? In core lib? I never will use this full of OOP anti-patterns ugly language. Why should I care on it in my app?

Why should I pay for all this useless stuff?

I'm tried to use ProGuard to get rid all unused classes and methods. But it seems no way for Spring Boot, Hibernate etc which are using Reflection API, AOP and even debug information! ProGuard was not able even to finish with no errors complaining on lack of some classes.

Another idea to use jlink, GraalVM native image and native build. And I found bunch of articles on that. For my understanding it is impossible to use it for Spring Boot app at this time.

Spring Boot is nice tool to build the apps.

QUESTION: is there a way to get rid all unused stuff from your final Spring Boot jar/war?

1

There are 1 best solutions below

2
Shailesh Chandra On

Please read about Spring Boot Maven Plugin It explains how you can exclude dependency during packaging,

By default, both the repackage and the run goals will include any provided dependencies that are defined in the project. A Spring Boot project should consider provided dependencies as container dependencies that are required to run the application

There are two ways one can exclude a dependency from being packaged/used at runtime

  1. Exclude a specific artifact identified by groupId and artifactId (optionally with a classifier if needed)
  2. Exclude any artifact belonging to a given groupId

however I doubt if you can remove anything inside any artifact

<plugins>
  ...
  <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.1.8.RELEASE</version>
    <configuration>
      <excludes>
        <exclude>
          <groupId>com.foo</groupId>
          <artifactId>bar</artifactId>
        </exclude>
      </excludes>
    </configuration>
    ...
  </plugin>
  ...
</plugins>

Also you can handle it at dependency level using exclusions

 <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </exclusion>
        </exclusions>
    </dependency