Introduction to Micronaut 4.0

Overview

This document presents a high-level understanding of the Micronaut 4.0 framework. We will understand some basic concepts like GraalVM, runtime reflection, JIT (Just In Time compiler) vs AOT (Ahead Of Time compiler) and the basic features of Micronaut 4.0.

What is Ahead Of Time Compilation

Ahead of Time compilation (AOT) is one way of improving JVM performance, particularly by improving the start-up time. To understand this, we first need to understand how the JVM works. With Java, we first convert our high-level code to byte-code using javac (java compile), and then we execute and convert our byte-code to machine code using the interpreter. The byte-code is portable across different machines, which is the big advantage of the JIT compiler. The interpreter inside the JVM does the translation from byte-code to machine code depending on the machine the byte-code is executed on. There are various optimisations the JVM does such as constant inlining, loop unrolling, and partial evaluation at compilation time. 

How the JVM does performance optimisation

The JVM optimises code based on something called profiling. It keeps track of frequently called methods, or more frequently used code, and precompiles it into machine code, and stores it in the cache-load. Next time this cached method or code is executed, it uses the cache-load to save time on the conversion. This caching is done by the JIT (Just in Time Compiler).

The drawback of cache-load is a minor increase in memory usage despite not significantly improving the startup time.

What is AOT Compilation

AOT compilation is a form of static compilation wherein the program is transformed into a machine code before it is executed. This means it converts byte-code directly into the native machine code of the executing machine during the compilation phase. The compiler used to do this is known as Graal/GraalVM. The GraalVM compiler can perform a highly optimised AOT compilation of JVM byte-code. This means it executes faster with less overhead, which translates into optimal resource consumption, with less CPU and memory usage.

What is Java Annotation Processing.

it is a processor that hook’s into the compile process of the java compiler, to analyse the source code for user defined annotations and handle then (by producing compiler errors, compiler warning, emitting source code, byte code, etc). An annotation by itself does not perform any action. It simply provides information that can be used at compile time or runtime to perform further processing. We can also create our own Custom annotation, below is example using reflection APIClick here see custom annotation.

  • Output when we the run the main class

What is GraalVM

It is a high performance runtime which provides significant optimisations. Graal is based off of Java SE, but also support other languages like Python, Ruby, Javascript etc.

Java Applications will use JIT compilation by default, but with GraalVM we can turn on AOT mode, which will offer us the above advantages.

With GraalVM you have two options: 1. We can still follow JIT-mode for default compilation. 2. Enable the AOT compiler to produce native images/executables (which are faster). Below are some advantages of native images:

Native Image goals.

What is Micronaut

It is a JVM-based, full stack Java framework designed for building modular, easily testable JVM applications. We will mainly be using it to build microservices and Cloud Native APIs. Supported languages are Java, Kotlin, and Groovy.

Micronaut 4 now requires a minimum of Java 17 for building and running applications. 

This framework is designed to support solutions for any application type, e.g. microservices, command line applications, message driven producers and consumers, and serverless functions.


Core Understanding

  1. It uses Java annotation processor to process these annotations(@Inject @Controller etc) at compile time or runtime to provide functionality such as code generation, error checking, etc.Micronaut uses annotations at compile time. This allows Micronaut to perform startup analysis and optimize the application’s performance
  2. It is highly optimised which results is less CPU Usage, Less memory consumption and hence less monthly billing😊 if you are running application in cloud (Like OCI).
  3. As most of the things are done at compile time it has better start-up time. 
  4. As we have already understood what is AOT, Micronaut uses AOT under the hood to generate and compute project at build time.

Fundamentals

Reflection

The term reflection is used to describe code which is able to inspect other code in the same system. Example let say you have Person or Employee class and it has a getName() method. Reflection can inspect an object at runtime to determine if a ‘getName()’ method exists

Class<?> dynamicClass = Class.forName("com.example.DynamicClass");
Method dynamicMethod = dynamicClass.getMethod("someMethod");
// Invoke the dynamically loaded method on an object
dynamicMethod.invoke(dynamicObject);

Using java reflection we can inspect a class, interface, enum, get their structure, methods and fields information at runtime even though class is not accessible at compile time

  1. Some real time use case of Reflection in Java
    1. JUnit – uses reflection to parse @Test annotation to get the test methods and then invoke it.
    2. Spring – dependency injection, read more at Spring Dependency Injection
  2. We know reflection is powerful but its expensive as it does all during the runtime, which makes the application start-up/warming-up slow. It increases memory consumption.

Dependency Injection 

How Spring uses it

Classpath Scanning

  • A Classpathscanning basically means, detecting the classes that need to be managed by the Framework under a specified package. In Spring we use something called @ComponentScan annotation to scan class and @Configuration for classpath scanning. 
  • Java classpathThe “java.class.path” system property, if set properly (FYI, maven doesn’t set it properly), can be a way to obtain a list of classpath/archives you can scan for annotated classes. Although it it only provides relative paths, you can easily turn these into URLs and/or InputStreams for iterating over.

Micronaut Core Feature’s

  • Micronaut does everything at compile as shown above.
  • Dependency Injection, bean Introspection, Wiring of Object (Object association) are all done ahead of time(compile time) and they are indexed to improve performance.
  • The approach Micronaut took is to hook everything in the compilation phase which made compilation time to be more but application start-up time to be lower
  • Micronaut build size is very small as it uses just 2-3 classes and its general purpose framework.
  • It uses GraalVM metadata repository
    • This repository enables users of GraalVM Native Image to share and reuse metadata for libraries and frameworks in the Java ecosystem. The repository is integrated with GraalVM Native Build Tools beginning with version 0.9.
  • Introduced new feature which is Annotation Based CORS Configuration.
  • It is smaller and lighter runtime.
  • Now with Micronaut 4.0 it has http3 support.
  • It uses java annotation processor that computes the application code at compile time.
  • It uses Netty as embedded server (Spring uses Tomcat, dropwizard uses jetty).
  • As Micronaut does not favour reflection and it is suggested to use Micronaut Serialization which offers reflection-free serialization using build-time Bean Introspections

Micronaut other feature’s

Micronaut and GraalVM

Micronaut Solutions

Leave a Reply