SpringOne 2020
The Path Towards Spring Boot Native Applications
Sébastien Deleuze, Spring Framework Committer at VMware
Andy Clement, Director at VMware
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
The Path Towards Spring Boot Native Applications
1. The Path Towards Spring
Boot Native Applications
September 2–3, 2020
springone.io
Join https://springone.slack.com #session-the-path-towards-spring-boot-native-applications
1
Andy Clement
Sébastien Deleuze
2. Safe Harbor Statement
The following is intended to outline the general direction of VMware's offerings. It is intended for information
purposes only and may not be incorporated into any contract. Any information regarding pre-release of
VMware offerings, future updates or other planned modifications is subject to ongoing evaluation by
VMware and is subject to change. This information is provided without warranty or any kind, express or
implied, and is not a commitment to deliver any material, code, or functionality, and should not be relied
upon in making purchasing decisions regarding VMware's offerings. These purchasing decisions should only
be based on features currently available. The development, release, and timing of any features or
functionality described for VMware's offerings in this presentation remain at the sole discretion of Pivotal.
Pivotal has no obligation to update forward looking information in this presentation.
2
3. Agenda
● Native applications
● Spring Boot native applications
● Where are we?
● Getting started
● Demo
● spring-graalvm-native
● The road ahead
3
7. 7
Scale to zero
You only pay when your application is
used
Serverless for any kind of workload
including regular web applications
Good fit with platforms like Knative
3x to 5x memory reduction (RSS)
Cheaper cloud instances
Critical with systems splitted into multiple
microservices
Instant Startup
Reduced memory
consumption
Our goal is cheaper hosting of your Spring Boot applicationsCheaper and more sustainable Spring Boot applications
7
9. Key differences between JVM and native
9
● Static analysis of your application from the main entry point
● Configuration required for:
○ Reflection
○ Proxies
○ Resources
● Classpath fixed at build time
● No class lazy loading
● Some code will run at build time
18. Our goal is to support compilation of existing or
new Spring Boot applications to native
executables. Unchanged.
18
19. “We are excited about the great partnership between the Spring and
GraalVM engineering teams to support native ahead-of-time
compilation for millions of Spring Boot applications. This is a game
changer enabling low memory footprint and instant startup for these
workloads.”
Thomas Wuerthinger, GraalVM founder & project lead
19
Collaboration between Spring and GraalVM teams
20. Leverage Spring Boot container image support
2
0
> mvn spring-boot:build-image
or
> gradle bootBuildImage
28. spring-graalvm-native
● Incubating Spring Boot native application support
○ It includes a plugin for the GraalVM native image builder
● Analyses the Spring Boot application at build time
○ Computes the most optimal native image configuration
○ Challenge is doing that with static analysis
● Also perform some build time transformation for:
○ Optimized footprint
○ Compatibility
28
29. We have just released 0.8.0
● GraalVM 20.2 baseline
● Use Spring Boot 2.4.0 latest milestone
● Significant footprint improvements
● Wider range of supported technology
● New experimental functional mode
● Spring Boot lightweight container integration
○ Maven
○ Gradle
29
30. Patch updates until Spring Boot 2.4.0
● 0.8.1 (September 2020)
○ Upgrade to Spring Boot 2.4.0-M3
● 0.8.2 (October 2020)
○ Upgrade to Spring Boot 2.4.0-RC1
● 0.8.3 (November 2020)
○ Upgrade to Spring Boot 2.4.0
○ GraalVM 20.3 baseline
30
31. Starters supported in 0.8.x
● Actuator
● Cache
● Data JPA, MongoDB, R2DBC, Redis
● JDBC
● Logging (Logback)
● Thymeleaf
● Validation
● Web (Spring MVC with Tomcat)
● Webflux (Netty)
● Wavefront
● Spring Cloud Function
31
33. Comparing Spring Boot 2.3 LoggingSystem ...
33
Map<String, String> systems = new LinkedHashMap<>();
systems.put("ch.qos.logback.core.Appender",
"org.springframework.boot.logging.logback.LogbackLoggingSystem");
systems.put("org.apache.logging.log4j.core.impl.Log4jContextFactory",
"org.springframework.boot.logging.log4j2.Log4J2LoggingSystem");
systems.put("java.util.logging.LogManager",
"org.springframework.boot.logging.java.JavaLoggingSystem");
SYSTEMS = Collections.unmodifiableMap(systems);
34. … with Spring Boot 2.4 one
34
ClassLoader classLoader = LoggingSystem.class.getClassLoader();
if (ClassUtils.isPresent("ch.qos.logback.core.Appender", classLoader)) {
return LogbackLoggingSystem::new;
}
if (ClassUtils.isPresent("org.apache.logging.log4j.core.impl.Log4jContextFactory", classLoader)) {
return Log4J2LoggingSystem::new;
}
if (ClassUtils.isPresent("java.util.logging.LogManager", classLoader)) {
return JavaLoggingSystem::new;
}
throw new IllegalStateException("No suitable logging system located");
35. New flags available in Spring Framework 5.3
# -3.6M RSS
-Dspring.xml.ignore=true
# -0.5M RSS
-Dspring.spel.ignore=true
35
36. A new Tomcat artifact optimized for native apps
<!-- -3.5M RSS -->
<dependency>
<groupId>org.apache.tomcat.experimental</groupId>
<artifactId>tomcat-embed-programmatic</artifactId>
<version>9.0.38</version>
</dependency>
36
39. Make sure to use Spring Boot 2.4 latest milestone
39
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0-M2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
40. Update configuration to avoid using proxies
40
@SpringBootApplication(proxyBeanMethods = false)
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
43. Build the native application
43
> mvn spring-boot:build-image
Successfully built image 'docker.io/library/demo:0.0.1-SNAPSHOT'
Total time: 60 s
● No need for a GraalVM native local install
● Build happens in a container
● And produces a container
47. Build the native application
47
> mvn -Pnative clean package
Total time: 60 s
● Need for a GraalVM native local install
● Build happens directly on your host (Linux, Mac and Windows are
supported)
● Produces a native executable
● No cross compilation
50. How fast is your PetClinic?
50
Sample On the JDK native-executable
petclinic-jdbc Build: 9s
Memory(RSS): 417M
Startup time: 2.6s
Build: 194s +2050%
Memory(RSS): 101M -75%
Startup time: 0.158s -94%
53. For additional native configuration (eg. resources)
● Create a META-INF/native-image/resource-config.json file
● Wildcard patterns can be used
● Similar config for reflection and proxies
● See GraalVM documentation for more details
{
"resources": [
{ "pattern": "myresource.*" }
],
"bundles": [
{ "name": "your.pkg.Bundle" }
]
}
53
54. Tracing agent collected configuration
● An agent can assist in generating these files, available with GraalVM
java -Dorg.graalvm.nativeimage.imagecode=agent
-agentlib:native-image-agent=config-output-dir=META-INF/native-image Demo
● Agent has improved greatly during 2020, thanks to the GraalVM team
● Run application with agent attached to produce .json files
○ Exercise all code paths (manually or via tests) - producing (merging) many of
these collected configurations
● Access filter file supported to avoid including unnecessary infrastructure
5
4
57. Project structure and extensibility
● Core static analysis engine for Spring Applications
○ static: behaviour driven by separate ‘hints’
○ dynamic: extensible with Spring portfolio project awareness via plugins
● @NativeImageHint
○ Same information as JSON, but more modular, more type safe
○ hints attached to a trigger - an auto configuration active or a classpath
presence check
○ application analysis determines if triggers are active => activates those
hints
57
58. Hint with auto-configuration trigger
@NativeImageHint(trigger = R2dbcAutoConfiguration.class,
proxyInfos = {
@ProxyInfo(types={Serializable.class, InterfaceFoo.class})
},
typeInfos= {
@TypeInfo(types = EmbeddedDatabase.class,
access = AccessBits.LOAD_AND_CONSTRUCT)
}
)
public class R2dbcHints implements NativeImageConfiguration {
}
58
61. spring-graalvm-native 0.9.0 (December 2020)
● First release with beta support
○ Spring Boot 2.4.0 and GraalVM 20.3 baseline
○ Subset of starters supported
○ Breaking change will happen (with upgrade paths)
● Wider support
○ Spring Security
○ Spring Batch
● Development-oriented container image
61
63. Hidden gem in Spring Framework since 5.0:
functional bean registration
63
64. Comparing annotation and functional bean definition
@Configuration
public class SampleConfiguration {
@Bean
public Foo foo() {
return new Foo();
}
@Bean
public Bar bar(Foo foo) {
return new Bar(foo);
}
}
64
public class SampleInitializer implements
ApplicationContextInitializer<GenericApplicationContext> {
@Override
public void initialize(GenericApplicationContext ctx) {
ctx.registerBean(Foo.class, () -> new Foo());
ctx.registerBean(Bar.class,
() -> new Bar(ctx.getBean(Foo.class)));
}
}
65. @Configuration to functional configuration
65
Automated
transformation
from @Configuration
to functional
configuration
67. Native applications functional configuration
67
Sample webmvc-tomcat webmvc-functional
With build time transformation to
functional configuration
Regular Spring Boot
application with Spring MVC,
Tomcat and Jackson
Build: 67s
Exec. size: 42M
Memory(RSS): 51M
Startup time: 0.06s
Build: 60s -10%
Exec. size: 37M -12%
Memory(RSS): 26M -49%
Startup time: 0.02s -66%
68. Experimentations on more build time transformations
● @Configuration to functional configuration transformation with
spring-init
● Infer proxyBeanMethods = false when possible
● Automatically set optimization flags when relevant
68
69. Spring Boot 3, based on Spring Framework 6, is
expected to provide first-class support for native
application deployment, as well as an optimized
footprint on the JVM.
69
70. Takeaways
● Spring Boot native applications are great to build lightweight containers
● Try it now with spring-graalvm-native 0.8
● Contribute support for your favorite starter
● Beta support in December with spring-graalvm-native 0.9
● Wider support and smaller footprint during 0.9.x releases
● Upcoming first-class native support in Spring Boot 3 / Framework 6
70