Evolving Java for the Microservice and Serverless Era
About Me • Graeme Rocher • Creator of Grails and Micronaut • Principal Engineer at Object Computing • 2018 Oracle Groundbreaker Award Winner • Java Champion
Agenda • Challenges Facing Java • Introduction to Micronaut • Micronaut's Approach to Solving The Problems • Demos!
Java and Serverless • Challenges to using Java in Serverless / Microservices scenarios • Existing Tools and Frameworks Not Optimized for Cold Starts / Low Memory • Go, Node etc. better in this regards • Tim Bray (Amazon/AWS) and others not recommending Java https://youtu.be/IPOvrK3S3gQ?t=1109
Java's Problems for Frameworks • Limited Annotation API • Type Erasure • Slow Reflection • Reflective Data Caches • Classpath Scanning • Slow Dynamic Class Loading
Java's Problems • Greatly Exaggerated (Java has been dead forever) • Java can be Fast! (see Android and Micronaut) • However Most Existing Tools are based around • Reflection • Runtime Proxies • Runtime Byte Code Generation (bytebuddy/cglib)
Why is Reflection a Problem? • Today the JDK is OpenJDK! • Just take a look... http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/ share/classes/java/lang/Class.java#l2471 • All Reflective data initialized on first access and held in soft references (yes every field, method etc.) • Won't be GC'ed until your application is low on memory!
Avoid Reflection! • Reflection usages increases memory usage • Using reflection relatively slow • Problem is most modern server-side frameworks and specifications are built on reflection • Some of the Jarkarta specifications even mandate reflection
Just Like The Android World • The Android Community already solved the problem • Ahead of Time Compilation used extensively • Google Dagger 2.x for DI • Most Android Frameworks avoid reflection to avoid paying the memory / performance cost
Micronaut • A Microservices and Serverless Focused framework (hence the branding) • Also a Complete Application Framework for any type of Application • Dependency Injection, Aspect Oriented Programming (AOP), Configuration Management, Bean Introspection and more..
With Micronaut You Can Build • Microservices • Serverless Applications • Message-Driven Applications with Kafka/Rabbit • CLI Applications • Even Android Applications • Anything with static void main(String..args)
So What is Micronaut? Really? • An Application Framework for the Future • Reflection Free, Runtime Proxy Free, No Dynamic Classloading (in 1.1) • Ahead of Time (AOT) Compilation AOT APIs • ... oh and let's you build Microservices
Micronaut and GraalVM • A New Universal Virtual Machine from Oracle • Features a native-image Tool • Converts Java -> native machine code using AOT • Works well with Micronaut • Startup time 20ms and Memory Consumption 18MB! http://www.graalvm.org
Micronaut's Solutions Problem Solution Limited Annotation API Precomputed AnnotationMetadata Type Erasure Precomputed Argument Interface Slow Reflection Eliminate Reflection Reflective Data Caches Zero Data Caches Classpath Scanning No Classpath Scanning Slow Dynamic Class Loading No Dynamic Class Loaders
DEMOMicronaut Bean Introspection
@Introspected @Introspected class MyBean { private List<String> names; //getter/setter omitted } • AOT Reflection-free replacement for java.beans.Introspector • Set/get bean properties, create instances • Includes AnnotationMetadata
AnnotationMetadata AnnotationMetadata metadata = BeanIntrospection.getIntrospection(MyBean.class) .getAnnotationMetadata(); if (metadata.hasStereotype(SomeAnnotation.class)) { // do stuff } • AOT Computed / Merged Annotation Replacement for Reflection based API • Includes knowledge of meta-
AnnotationMetadata Why? • All the Nullable annotations!!! • javax.annotation.Nullable (Java) • org.jetbrains.annotations. Nullable (Kotlin) • edu.umd.cs.findbugs. annotations.Nullable (Spotbugs) • org.springframework. lang.Nullable (Spring)
Argument BeanProperty<MyBean, List> property = introspection.getRequireProperty("names", List.class); // returns an Argument with an underlying type of String Optional<Argument> typeVariable = property.asArgument() .getFirstTypeVariable() • AOT Computed Generic Type information • No type erasure / crazly reflection logic to get the type argument
Argument Why? • You think resolving generic types in simple? https://github.com/spring-projects/ spring-framework/blob/master/spring- core/src/main/java/org/ springframework/core/ ResolvableType.java
DEMOMicronaut Dependency Injection
BeanDefinition ApplicationContext ctx = ApplicationContext.run(); BeanDefinition<MyBean> definition = ctx.getBeanDefinition(MyBean.class); • Contains precomputed AnnotationMetadata and generic type info • Used by ApplicationContext to instantiate beans
BeanDefinition • Bean definitions produced for any @Singleton • Constructor injection used by default • Use @Factory for beans you cannot annotate • Compliant with javax.inject spec and TCK
@ConfigurationProperties Type Safe Configuration @ConfigurationProperties("example") class ExampleConfiguration { // getters/setters omitted private String name; } ApplicationContext context = ApplicationContext.run("example.name":"Demo"); FooConfiguration config = context.getBean(FooConfiguration); assert config.name == 'Demo'
@Requires Conditional Beans Made Easy @Requires(property="example.enabled") @Requires(beans=DataSource.class) @Requires(missingBeans=Example.class) @Singleton class DefaultExampleBean implements Example { ... } ApplicationContext context = ApplicationContext.run("example.enabled":"true") Example example = context.getBean(Example)
@Executable @Scheduled(fixedRate = "5m") // @Scheduled annotated with @Executable void everyFiveMinutes() { messageService.sendMessage("Hello World"); } • Common Stereotype annotation • Identifies where framework invokes your code • Produces reflection-free ExectubleMethod instance
@ExecutableMethodProcessor public class ScheduledMethodProcessor implements ExecutableMethodProcessor<Scheduled> { public void process(BeanDefinition<?> beanDefinition, ExecutableMethod<?, ?> method) { // do stuff with the bean } } • Processes only methods annotated by type argument • In the above case setting up a scheduled job
DEMOMicronaut AOP
@Around @Retryable // @Retryable is annotated with @Around void invokeMe() { // do stuff } • Intercepts a method with a MethodInterceptor • No runtime proxies (compile time proxies) or reflection needed • No FancyProxyFactoryBean or containers needed!
@Around @Around @Type(DefaultRetryInterceptor.class) public @interface Retryable { // annotation attributes } • Use @Type to specify the implementation • At compilation Micronaut applies the AOP advise
DEMOMicronaut
Micronaut Startup and Memory Runtime Memory Startup JDK 11 75MB 1.1s JDK 13 75MB 900ms JDK 13 + CDS 75MB 400ms GraalVM Substrate 15MB 21ms
Summary • Micronaut Provides an Awesome Set of Framework Primitives • Sacrifices Compilation Speed to Gain so Much More • Solves Problems with Spring, Jakarta EE and Java in General • Opens the Door to GraalVM Native • Come learn more in my "Micronaut Deep Dive" talk at 6PM!
Q & A
Micronaut: Evolving Java for the Microservices and Serverless Era
Micronaut: Evolving Java for the Microservices and Serverless Era

Micronaut: Evolving Java for the Microservices and Serverless Era

  • 1.
    Evolving Java forthe Microservice and Serverless Era
  • 2.
    About Me • GraemeRocher • Creator of Grails and Micronaut • Principal Engineer at Object Computing • 2018 Oracle Groundbreaker Award Winner • Java Champion
  • 3.
    Agenda • Challenges FacingJava • Introduction to Micronaut • Micronaut's Approach to Solving The Problems • Demos!
  • 4.
    Java and Serverless •Challenges to using Java in Serverless / Microservices scenarios • Existing Tools and Frameworks Not Optimized for Cold Starts / Low Memory • Go, Node etc. better in this regards • Tim Bray (Amazon/AWS) and others not recommending Java https://youtu.be/IPOvrK3S3gQ?t=1109
  • 5.
    Java's Problems for Frameworks •Limited Annotation API • Type Erasure • Slow Reflection • Reflective Data Caches • Classpath Scanning • Slow Dynamic Class Loading
  • 6.
    Java's Problems • GreatlyExaggerated (Java has been dead forever) • Java can be Fast! (see Android and Micronaut) • However Most Existing Tools are based around • Reflection • Runtime Proxies • Runtime Byte Code Generation (bytebuddy/cglib)
  • 7.
    Why is Reflectiona Problem? • Today the JDK is OpenJDK! • Just take a look... http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/ share/classes/java/lang/Class.java#l2471 • All Reflective data initialized on first access and held in soft references (yes every field, method etc.) • Won't be GC'ed until your application is low on memory!
  • 8.
    Avoid Reflection! • Reflectionusages increases memory usage • Using reflection relatively slow • Problem is most modern server-side frameworks and specifications are built on reflection • Some of the Jarkarta specifications even mandate reflection
  • 9.
    Just Like The AndroidWorld • The Android Community already solved the problem • Ahead of Time Compilation used extensively • Google Dagger 2.x for DI • Most Android Frameworks avoid reflection to avoid paying the memory / performance cost
  • 10.
    Micronaut • A Microservicesand Serverless Focused framework (hence the branding) • Also a Complete Application Framework for any type of Application • Dependency Injection, Aspect Oriented Programming (AOP), Configuration Management, Bean Introspection and more..
  • 11.
    With Micronaut You CanBuild • Microservices • Serverless Applications • Message-Driven Applications with Kafka/Rabbit • CLI Applications • Even Android Applications • Anything with static void main(String..args)
  • 12.
    So What is Micronaut?Really? • An Application Framework for the Future • Reflection Free, Runtime Proxy Free, No Dynamic Classloading (in 1.1) • Ahead of Time (AOT) Compilation AOT APIs • ... oh and let's you build Microservices
  • 13.
    Micronaut and GraalVM • ANew Universal Virtual Machine from Oracle • Features a native-image Tool • Converts Java -> native machine code using AOT • Works well with Micronaut • Startup time 20ms and Memory Consumption 18MB! http://www.graalvm.org
  • 14.
    Micronaut's Solutions Problem Solution LimitedAnnotation API Precomputed AnnotationMetadata Type Erasure Precomputed Argument Interface Slow Reflection Eliminate Reflection Reflective Data Caches Zero Data Caches Classpath Scanning No Classpath Scanning Slow Dynamic Class Loading No Dynamic Class Loaders
  • 15.
  • 16.
    @Introspected @Introspected class MyBean { privateList<String> names; //getter/setter omitted } • AOT Reflection-free replacement for java.beans.Introspector • Set/get bean properties, create instances • Includes AnnotationMetadata
  • 17.
    AnnotationMetadata AnnotationMetadata metadata =BeanIntrospection.getIntrospection(MyBean.class) .getAnnotationMetadata(); if (metadata.hasStereotype(SomeAnnotation.class)) { // do stuff } • AOT Computed / Merged Annotation Replacement for Reflection based API • Includes knowledge of meta-
  • 18.
    AnnotationMetadata Why? • All theNullable annotations!!! • javax.annotation.Nullable (Java) • org.jetbrains.annotations. Nullable (Kotlin) • edu.umd.cs.findbugs. annotations.Nullable (Spotbugs) • org.springframework. lang.Nullable (Spring)
  • 19.
    Argument BeanProperty<MyBean, List> property= introspection.getRequireProperty("names", List.class); // returns an Argument with an underlying type of String Optional<Argument> typeVariable = property.asArgument() .getFirstTypeVariable() • AOT Computed Generic Type information • No type erasure / crazly reflection logic to get the type argument
  • 20.
    Argument Why? • You thinkresolving generic types in simple? https://github.com/spring-projects/ spring-framework/blob/master/spring- core/src/main/java/org/ springframework/core/ ResolvableType.java
  • 21.
  • 22.
    BeanDefinition ApplicationContext ctx =ApplicationContext.run(); BeanDefinition<MyBean> definition = ctx.getBeanDefinition(MyBean.class); • Contains precomputed AnnotationMetadata and generic type info • Used by ApplicationContext to instantiate beans
  • 23.
    BeanDefinition • Bean definitionsproduced for any @Singleton • Constructor injection used by default • Use @Factory for beans you cannot annotate • Compliant with javax.inject spec and TCK
  • 24.
    @ConfigurationProperties Type Safe Configuration @ConfigurationProperties("example") classExampleConfiguration { // getters/setters omitted private String name; } ApplicationContext context = ApplicationContext.run("example.name":"Demo"); FooConfiguration config = context.getBean(FooConfiguration); assert config.name == 'Demo'
  • 25.
    @Requires Conditional Beans MadeEasy @Requires(property="example.enabled") @Requires(beans=DataSource.class) @Requires(missingBeans=Example.class) @Singleton class DefaultExampleBean implements Example { ... } ApplicationContext context = ApplicationContext.run("example.enabled":"true") Example example = context.getBean(Example)
  • 26.
    @Executable @Scheduled(fixedRate = "5m")// @Scheduled annotated with @Executable void everyFiveMinutes() { messageService.sendMessage("Hello World"); } • Common Stereotype annotation • Identifies where framework invokes your code • Produces reflection-free ExectubleMethod instance
  • 27.
    @ExecutableMethodProcessor public class ScheduledMethodProcessor implementsExecutableMethodProcessor<Scheduled> { public void process(BeanDefinition<?> beanDefinition, ExecutableMethod<?, ?> method) { // do stuff with the bean } } • Processes only methods annotated by type argument • In the above case setting up a scheduled job
  • 28.
  • 29.
    @Around @Retryable // @Retryableis annotated with @Around void invokeMe() { // do stuff } • Intercepts a method with a MethodInterceptor • No runtime proxies (compile time proxies) or reflection needed • No FancyProxyFactoryBean or containers needed!
  • 30.
    @Around @Around @Type(DefaultRetryInterceptor.class) public @interface Retryable{ // annotation attributes } • Use @Type to specify the implementation • At compilation Micronaut applies the AOP advise
  • 31.
  • 32.
    Micronaut Startup andMemory Runtime Memory Startup JDK 11 75MB 1.1s JDK 13 75MB 900ms JDK 13 + CDS 75MB 400ms GraalVM Substrate 15MB 21ms
  • 33.
    Summary • Micronaut Providesan Awesome Set of Framework Primitives • Sacrifices Compilation Speed to Gain so Much More • Solves Problems with Spring, Jakarta EE and Java in General • Opens the Door to GraalVM Native • Come learn more in my "Micronaut Deep Dive" talk at 6PM!
  • 34.