Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Browser testing is essential if you have a website or web applications that users interact with. Manual testing can be very helpful to an extent, but given the multiple browsers available, not to mention versions and operating system, testing everything manually becomes time-consuming and repetitive.

To help automate this process, Selenium is a popular choice for developers, as an open-source tool with a large and active community. What's more, we can further scale our automation testing by running on theLambdaTest cloud-based testing platform.

Read more through our step-by-step tutorial on how to set up Selenium tests with Java and run them on LambdaTest:

>> Automated Browser Testing With Selenium

Partner – Orkes – NPI EA (cat=Java)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

1. Overview

When we run a Java application, the JVM undertakes an intricate series of steps before our code executes. In this tutorial, we’ll look at what happens from the moment we run the java command until our application starts up.

Using a simple HelloWorld program as an example, we’ll break down each stage of the process. Understanding these internal mechanisms can significantly enhance the effectiveness of debugging and performance tuning.

2. From java Command to JVM Launch

Before the JVM can execute any code, it must first launch, validate inputs, and configure its environment. Here, we walk through the early startup sequence, from invoking the java command to initializing the JVM runtime.

2.1. The java Command and Initial Invocation

When we run the java command, the JVM startup sequence begins by invoking the JNI method JNI_CreateJavaVM(). This method carries out several essential initialization tasks that prepare the environment for executing Java applications. The Java Native Interface (JNI) acts as a bridge between the JVM and the native system libraries. It enables seamless two-way communication between Java code and platform-specific functionality.

Throughout this article, we’ll use detailed logging to observe how the JVM operates internally using:

java -Xlog:all=trace HelloWorld

2.2. Validating User Input

First, the JVM validates the arguments we pass:

[0.006s][info][arguments] VM Arguments:
[arguments] jvm_args: -Xlog:all=trace:file=helloworld.log 
[arguments] java_command: HelloWorld
[arguments] java_class_path (initial): .
[arguments] Launcher Type: SUN_STANDARD

The JVM verifies the target artifact, classpath, and any JVM arguments to make sure they’re valid before moving forward. This validation step helps catch many common configuration errors early in the startup process, preventing them from causing issues later on.

2.3. Detecting System Resources

Next, the JVM identifies the system resources available to it, such as the number of processors, the amount of memory, and key system services:

[0.007s][debug][os       ] Process is running in a job with 20 active processors.
[os       ] Initial active processor count set to 20
[os       ] Process is running in a job with 20 active processors.
[gc,heap  ]   Maximum heap size 4197875712
[gc,heap  ]   Initial heap size 262367232
[gc,heap  ]   Minimum heap size 6815736
[os       ] Host Windows OS automatically schedules threads across all processor groups.
[os       ] 20 logical processors found.

This information guides several internal decisions the JVM makes, such as which garbage collector to select by default. The number of available CPUs and the total memory directly influence the JVM’s heuristics. Most of these settings, however, can be overridden with explicit JVM arguments. During this stage, the JVM also checks whether Native Memory Tracking is available and verifies access to various operating system utilities it might depend on. We can customize system resources with JVM parameters.

2.4. Preparing the Environment

The JVM then prepares the runtime environment by generating HotSpot performance data. This data is used by profiling tools like JConsole and VisualVM:

[perf,datacreation] name = sun.rt._sync_Inflations, dtype = 11, variability = 2, units = 4, dsize = 8, vlen = 0, pad_length = 4, size = 56, on_c_heap = FALSE, address = 0x000001f3085f0020, data address = 0x000001f3085f0050

This performance data typically gets stored in the system’s /tmp directory and continues to be generated throughout the startup process, concurrent with other initialization tasks.

3. Loading, Linking, and Initialization

Once the JVM environment is ready, it begins preparing our program for execution.

3.1. Choosing the Garbage Collector

One main step inside the JVM is the selection of garbage collection. As of JDK23, by default, the JVM selects the G1 GC unless the system has less than 1792MB and/or is a single-processor system:

[gc               ] Using G1
[gc,heap,coops    ] Trying to allocate at address 0x0000000705c00000 heap of size 0xfa400000
[os               ] VirtualAlloc(0x0000000705c00000, 4198498304, 2000, 4) returned 0x0000000705c00000.
[os,map           ] Reserved [0x0000000705c00000 - 0x0000000800000000), (4198498304 bytes)
[gc,heap,coops    ] Heap address: 0x0000000705c00000, size: 4004 MB, Compressed Oops mode: Zero based, Oop shift amount: 3
[pagesize         ] Heap:  min=8M max=4004M base=0x0000000705c00000 size=4004M page_size=4K

We can choose another garbage collector: Parallel GC, ZGC, and others, depending upon the specific JDK version and its distribution.

3.2. Cached Data Storage Loading

At this point, the JVM starts looking towards optimizations. The CDS is an archive of class files that have already been pre-processed, which improves the startup performance of the JVM:

[cds] trying to map [Java home]/lib/server/classes.jsa
[cds] Opened archive [Java home]/lib/server/classes.jsa

However, CDS is being replaced by AOT as a part of Project Leyden, which we’ll discuss later.

3.3. Creating the Method Area

The JVM then creates the method area, a special off-heap memory location that stores class data. HotSpot JVM implementations call this area metaspace. Class data stored here is eligible for removal if the associated class loader is no longer in scope:

[metaspace,map    ] Trying anywhere...
[metaspace,map    ] Mapped at 0x000001f32b000000

While the method area is not located in the JVM’s heap, the GC still manages it.

3.4. Class Loading

Class Loading is a three-step process – locating the binary representation, deriving the class from it, and loading it into the method area. It’s the ability to dynamically load classes that allows frameworks like Spring and Mockito to load classes generated on demand during the JVM’s runtime.

There are two ways we can load classes: either with the bootstrap class loader or with a custom class loader.
Now, with the help of the HelloWorld class, let’s understand what the JVM must first do:

public class HelloWorld extends Object {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

The JVM will load java.lang.Object and all its dependencies first. When classes are initially loaded, they exist in a largely hidden state, allowing important validation and housekeeping steps to occur.

Let’s look at the java.lang.Object‘s methods:

public class Object {
    public final native Class<?> getClass()
    public String toString()
    public boolean equals(Object obj)
}

These methods reference java.lang.Class and java.lang.String that must be loaded first. The JVM follows a lazy loading strategy, only loading classes when they’re actively referenced. However, the classes we discussed above in this section are eagerly loaded, as they’re fundamental to the JVM’s operation. The bootstrap class loader, instantiated during the JNI_CreateJavaVM(), handles all the class loading for a simple HelloWorld program.

3.5. Class Linking

Class Linking involves three sub-processes – Verification, Preparation, and Resolution. These steps don’t occur in order, as Resolution can happen anytime before Verification, to after class initialization. Verification ensures that the class structure is correct:

[class,init] Start class verification for: HelloWorld
[verification] Verifying class HelloWorld with new format
[verification] Verifying method HelloWorld.<init>()V

Classes inside the CDS have already been verified, so they skip this step, improving the startup performance. This is one of the key benefits of the CDS providers. During Preparation, the JVM initializes static fields with their default values. Any static variable without an explicit initializer gets its default value automatically.

At Resolution, the JVM resolves symbolic references in the Constant Pool. The Constant Pool stores all symbolic references for a class, and the JVM must resolve them before it can execute the corresponding instructions.

We can examine this using javap:

javap -verbose HelloWorld

This shows us the Constant Pool:

Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // "<init>":()V
   #7 = Fieldref           #8.#9          // java/lang/System.out:Ljava/io/PrintStream;
  #13 = String             #14            // Hello World

The constructor’s bytecode doesn’t directly contain addresses. It references symbolic entries in the Constant Pool (like #1), which describe methods and fields. During resolution, the JVM turns those symbolic entries into real memory references that can be executed:

 public HelloWorld();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 2: 0
        line 4: 4

The invokespecial instruction at line 1 references the Constant Pool entry #1, which provides the information needed to link to java.lang.Object’s constructor. The init indicates that this is a special method automatically generated by javac for each constructor. The JVM performs resolution lazily, triggering it only when it tries to execute an instruction in a class. Not all loaded classes will have their instructions executed.

3.6. Class Initialization

Class Initialization assigns values to static fields and executes static initializers. This is distinct from instance initialization, which occurs when we call a constructor. The special clinit method, which javac automatically generates, handles class initialization.

4. Optimizing JVM Startup Performance

Even though the JVM’s startup is efficient, there’s room for improvement. Let’s see some pointers.

4.1. Impact of Class Loading

To measure the total time taken for the JVM to start, load classes, link them, and execute our simple program, we can use the system’s time utility:

time java HelloWorld

This measures the wall-clock time from the moment the JVM process starts to when it exits. It includes class loading, linking, JIT warm-up, and program execution – not just the user code. For HelloWorld, the JVM loads approximately 400-450 classes during startup. On modern hardware, this entire process completes in around 60 ms, even with verbose logging enabled.

4.2. Project Leyden

Project Leyden aims to reduce startup time, time-to-peak performance, and memory footprint. JDK 24 introduced JEP 483: Ahead-of-Time Class Loading and Linking, which performs these operations ahead of time rather than at startup. 

This feature records the JVM behavior during a training run, stores that in a cache, and loads from that cache on subsequent startups. This will supersede the CDS acronym transition and ultimately lead to AOT to better encompass the new capabilities.

4.3. JVM Flags and Tuning

While there might be opportunities to optimize the startup performance through the use of static fields and initializers, we should approach this carefully. Spending time refactoring classes to push behavior into class loading phases might not yield measurable results. Given that most executed code comes from dependencies rather than our application code.

5. Conclusion

In this article, we explored the complex process the JVM goes through during startup, from validating user input to detecting the system resources to loading, linking, and initializing classes. We saw how the JVM prepares an entire runtime environment before executing our code, loading hundreds of classes, even for a simple HelloWorld application.

With upcoming improvements like Project Leyden’s AOT features, the startup performance will continue to improve.

 

Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)
guest
0 Comments
Oldest
Newest
Inline Feedbacks
View all comments