2. Disclaimer
This presentation may contain product features or functionality that are currently under
development.
This overview of new technology represents no commitment from VMware to deliver these
features in any generally available product.
Features are subject to change, and must not be included in contracts, purchase orders, or
sales agreements of any kind.
Technical feasibility and market demand will affect final delivery.
Pricing and packaging for any new features/functionality/technology discussed or
presented, have not been determined.
The information in this presentation is for informational purposes only and may not be incorporated into any contract. There is no
commitment or obligation to deliver any items presented herein.
3. Join the discussion
● Make sure you’ve already registered at
https://springone.io/register
● Go to https://springone.slack.com
● Sign in using your springone.io credentials
● Join #session-spring-native channel
● Discuss and provide feedback during the talk
● A link to Q&A session will be posted there at the
end of this talk
9. What is Spring Native
Spring Native provides beta support for compiling Spring Boot
applications to native executables with GraalVM, providing a
new way to deploy Spring Boot applications that then run
extremely efficiently.
11. Typical use cases
Sustainability
Smaller and cheaper instances
in the Cloud
Serverless
Instant startup
Kubernetes
Lighter pods, scalability & Knative
Microservices
Reduce the cost of splitting
12. Our goal
Allow developers to compile their Spring Boot applications to
native executables with as few changes as possible.
13. Challenges
On GraalVM side
● Some JVM features are not supported
● No class lazy loading
● Configuration required for reflection, proxies,
resources, etc.
● JVM libraries mostly untested on native
● Compatibility versus footprint
● Long build times
On Spring side
● Runtime reflection used with the annotation
based programming model
● API backward compatibility
● No major architectural change since based on
Spring Boot 2.x and Spring Framework 5.x
20. 2 ways of building native executables with Spring Native
Buildpacks
● Container based native builds based on
Buildpacks integration in Spring Boot
● Application compilation support
● Require Docker but not GraalVM native-image
compiler
● Produce a Linux container image
○ x86 is supported
○ ARM support work in progress, follow
https://github.com/buildpacks/lifecycle/iss
ues/435 for updates.
Native Build Tools
● Started as a collaboration between Spring and
GraalVM teams, and recently the Micronaut team
have joined us.
● https://github.com/graalvm/native-build-tools/
● Application compilation and testing support
● Require GraalVM native-image compiler
● Produce a native executable (no cross compilation)
○ Linux (x86, ARM)
○ MacOS (x86)
○ Windows (x86)
26. Native hints
// native-image option or trigger for other hints -> native-image.properties
@NativeHint(options = "--enable-https")
// Reflection -> reflect-config.json ; *.class resources -> resource-config.json
@TypeHint(types = Data.class, typeNames = "com.example.webclient.Data$SuperHero")
// Additional resource to include in the native executable -> resource-config.json
@ResourceHint(patterns = "custom.sql" )
// JDK dynamic proxy on interfaces -> proxy-config.json
@JdkProxyHint(types = { org.springframework.context.annotation.Lazy.class,
org.springframework.core.annotation.SynthesizedAnnotation.class})
// Class with serialization support -> serialization-config.json
@SerializationHint(types = org.springframework.samples.petclinic.model.Person.class)
// Used to configure which class should be initialized at build-time -> native-image.properties
@InitializationHint(types = com.google.protobuf.Extension.class,
initTime = InitializationTime.BUILD)
29. Ahead-of-time proxies usable on classes
// Typical security use case of a class proxy now supported on native
@Service
public class GreetingService {
public String hello() {
return "Hello!";
}
@PreAuthorize("hasRole('ADMIN')")
public String adminHello() {
return "Goodbye!";
}
}
// Hint for Build-time proxy on classes
-> Spring AOT plugin
@AotProxyHint(targetClass =
org.springframework.batch.core.launch.su
pport.SimpleJobOperator.class,
proxyFeatures = ProxyBits.IS_STATIC)
30. Compression support in Buildpacks
New in 0.11
● Buildpacks now supports compressing native
executables
● UPX allows 4x size reduction!
● Compression takes some time but native-image
has already long build time
● At runtime, startup is usually faster because
decompression is more than compensated by
less IO!
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder:tiny</builder>
<env>
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
<BP_BINARY_COMPRESSION_METHOD>upx</BP_BINARY_COMPRESSION_METHOD>
</env>
</image>
</configuration>
</plugin>
32. Spring AOT plugins
Spring AOT Maven and Gradle plugins perform powerful
build-time transformations on Spring Boot applications to
improve efficiency on native, and potentially on the JVM too!
33. Compiling a Spring Boot application to native
native-image
compiler
Spring AOT plugin
javac
javac
Spring Boot
application
sources
Application
bytecode
AOT
sources
Native
configuration
AOT
bytecode
Native
executable
34. AOT application context processing
Huge effort during the summer
done by Stéphane Nicoll and Brian
Clozel to process Spring
application context beans at
build-time.
New in 0.11
35. Spring AOT plugin deep dive
Generate
source code
Native
configuration
inference
AOT application
context processing
New in 0.11
Spring AOT plugin
@Conditional
filtering
Classpath spring.factories
Application
properties
@NativeHint
Programmatic
Spring
factories
AOT proxy
generation
javac
Application
bytecode
Programmatic
application
context
Bytecode with
AOT proxies
Native
configuration
36. Spring Boot regular runtime
SpringApplication
@Configuration
spring.factories
Reflection
Reflection
*.class
resources
ASM
class
reading
Generated
bytecode
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({Jsonb.class})
@ConditionalOnResource( resources = ...)
public class JsonbAutoConfiguration {
public JsonbAutoConfiguration() { }
@Bean
@ConditionalOnMissingBean
public Jsonb jsonb() {
return JsonbBuilder.create();
}
}
# Logging Systems
org.springframework.boot.logging.LoggingSystemFactory=
org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory,
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory,
org.springframework.boot.logging.java.JavaLoggingSystem.Factory
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=
org.springframework.boot.env.PropertiesPropertySourceLoader,
org.springframework.boot.env.YamlPropertySourceLoader
CGLIB
proxy
generation
37. Spring Boot runtime in AOT mode (JVM and native)
SpringApplication
AOT bytecode
Programmatic
application context
Programmatic Spring
factories
New in 0.11
public abstract class StaticSpringFactories {
public static MultiValueMap<Class, Supplier<Object>> factories = new LinkedMultiValueMap();
static {
factories.add(org.springframework.boot.logging.LoggingSystemFactory.class,
() -> new org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory());
factories.add(org.springframework.boot.logging.LoggingSystemFactory.class,
() -> new org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory());
factories.add(org.springframework.boot.logging.LoggingSystemFactory.class,
() -> new org.springframework.boot.logging.java.JavaLoggingSystem.Factory());
factories.add(org.springframework.boot.env.PropertySourceLoader.class,
() -> new org.springframework.boot.env.PropertiesPropertySourceLoader());
}
}
public class ContextBootstrapInitializer implements ApplicationContextInitializer<GenericApplicationContext> {
@Override
public void initialize(GenericApplicationContext context) {
context.getDefaultListableBeanFactory()
.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
BeanDefinitionRegistrar.of("commandlinerunnerApplication", CommandlinerunnerApplication.class)
.instanceSupplier(CommandlinerunnerApplication::new).register(context);
BeanDefinitionRegistrar.of("CLR", CLR.class).instanceSupplier(CLR::new).register(context);
BeanDefinitionRegistrar.of("propertySourcesPlaceholderConfigurer",
PropertySourcesPlaceholderConfigurer.class).instanceSupplier(() ->
PropertyPlaceholderAutoConfiguration.propertySourcesPlaceholderConfigurer()).register(context);
// ...
}
}
38. Spring AOT strategy
● Move most configuration reflection from runtime to build-time
● Reduce the amount of Spring infrastructure required at runtime
● Maven and Gradle plugins with source generation:
○ To keep good debuggability
○ Annotation processors were by-design too limited for our
needs
● At runtime, AOT mode is:
○ mandatory on native
○ optional on the JVM, enabled via
java -DspringAot=true
40. Build time
Details
● Build time in seconds
● Spring Boot 2.5
● GraalVM 21.1 for 0.10, GraalVM 21.2 for 0.11
● Java 11 on Linux
● Laptop, Intel Core i7 8850H @ 2.6 GHz, 32G RAM
41. Container image size
Details
● Container image size in Megabytes
● Spring Boot 2.5
● Liberica JDK 11.0.12 for JVM, GraalVM CE 21.1 for
0.10, GraalVM CE 21.2 for 0.11
● Java 11 on Linux
42. Deep dive into a minimal native container image
New in 0.11
43. Memory footprint
Details
● RSS memory footprint after startup in
Megabytes
● Spring Boot 2.5
● Liberica JDK 11.0.12 for JVM, GraalVM CE 21.1 for
0.10, GraalVM CE 21.2 for 0.11
● JVM application ran as an unpacked archive
● Java 11 on Mac
* Expect lower memory consumption in 0.11.0 with GraalVM 21.3 optimizations on reflection
44. Startup time
Details
● Startup time (including the JVM) in milliseconds
● Simple web application with Spring MVC +
Tomcat
● Spring Boot 2.5
● Liberica JDK 11.0.12 for JVM, GraalVM CE 21.1 for
0.10, GraalVM CE 21.2 for 0.11
● JVM application ran as an unpacked archive
● Java 11 on Linux
● Laptop, Intel Core i7 8850H @ 2.6 GHz, 32G
RAM
46. GraalVM 21.3 new baseline
● GraalVM 21.3
○ To be released October 19th
○ Major improvements to reflection support
○ Java 17 support
○ Removal of Java 8 support
● Spring Native 0.11.0
○ GraalVM 21.3 baseline
○ Current snapshots based on GraalVM 21.2
○ Java 11 and Java 17 support
New in 0.11
47. Distinguish between invoked and queried reflection
methods
● Proposal
○ Updated reflect-config.json capabilities to allow
specifying that only reflection metadata like annotations
are needed
○ Efficiency gains since it is mainly the reflective
invocation which is costly on native.
● Up to 20% measured footprint reduction with Spring
applications
● https://github.com/oracle/graal/issues/3566 for more details
New in 0.11
48. Reachability based native configuration
● Build-time class initialization was the main way to reduce
image size and memory footprint, but a dead-end in term of
compatibility
● Proposal
○ Add a whenTypeReachable predicate to
reflect-config.json
○ Allows to take advantage of the native image static
analysis
○ Make it possible to switch everything to runtime
initialization with low footprint
● https://github.com/oracle/graal/issues/3551 for more details
New in 0.11
49. Inlining of simpler reflections calls
New in 0.11
● Inlining done at build-time
when arguments are constants
and implementation simple
enough
● Avoid the new for reflection
config
● Behind a flag in GraalVM 21.2,
enabled by default in 21.3
● https://github.com/oracle/graal/
issues/2500 for more details
// Does not require reflect-config.json configuration
// because inlined at build-time
Class.forName("org.example.Foo")
.getDeclaredConstructor().newInstance();
// Same for this one!
BeanUtils.instantiateClass(Foo.class);
51. Spring Native 0.11.0
● Key features
○ AOT application context
○ GraalVM 21.3 with reflection optimizations
○ Java 11 and Java 17 support
○ Spring Boot 2.6.0
○ UPX compression for container images
● 0.11 milestones published shortly for feedback
● 0.11.0 to be released November 19th
○ Following Spring Boot 2.6.0 release
52. VMware Tanzu adds end-to-end native support
● VMware and Bellsoft now have a support
agreement in place that provides end-to-end
native support to VMware Tanzu customers via
Liberica Native Image Kit*
● Bellsoft Liberica NIK, based on the GraalVM
Community Edition and Liberica JDK, will be
used in native Buildpacks as of Spring Native
0.11.0
● Consistent with the JVM side where Liberica
JDK is used
● Fixes and enhancements will be contributed
upstream to https://github.com/oracle/graal
* https://bell-sw.com/pages/liberica-native-image-kit/
53. The future of Spring Native is
first-class native support in
Spring Boot 3.x
54. Spring Boot 3 AOT and native support overview
Native build tools
Native configuration
libraries
GraalVM Spring Boot 3
AOT support in
Maven and Gradle
plugins
AOT transformation
engine
Spring Framework 6
Paketo Buildpacks
Native Buildpack
Native foundational
support and key
enablers
GraalVM 22.x
Native support
Spring portfolio (Data, Security, etc.)
AOT transformations Minimal native hints
Architecture likely to change as we implement it
Roadmaps towards GA
● Spring Framework 6.0
○ 6.0 M1 in Q4 2021
○ 6.0 RC1 in Q3 2022
○ 6.0 GA in Q4 2022
● Spring Boot 3.0 GA to follow
● Migration from Spring Native
Goals
● Seamless integration in Spring Boot
● Increased native support
● Runtime efficiency via AOT
transformations for native and JVM
● Java 17 baseline
55. Collaboration with GraalVM team continue to increase
“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
56. Native configuration repository
● Native configuration for JVM libraries
○ Main goal remains direct inclusion in
libraries
○ This repository intends to fill the gap
● Automated testing via native build tools +
dedicated CI infrastructure
● Initially a GraalVM and Spring driven effort
● All non Spring native hints will be moved to this
repository
● Guidelines on how to craft native configuration
○ Runtime initialization by default
○ No or very limited build-time initialization
○ Reachability based native configuration
○ Mandatory native testing