JVM Initialization and Internal Structure

JVM Startup Sequence

Step 1: Execution Entry Point

The Java executable launches the JVM process using the java command. This invocation triggers a multi-stage initialization sequence that prepares the runtime environment before executing any user code.

Step 2: Configuration Loading

The JVM searches for the jvm.cfg file based on the current working directory and system architecture. This configuration file lists available JVM implementations in preference order, where the first entry becomes the default selection. Different software products bundling a JVM include their own version of this file with implementation-specific settings.

Typical jvm.cfg format from an Oracle JDK installation:

# Copyright (c) 2003, 2013, Oracle and/or its affiliates.
# ORACLE PROPRIETARY/CONFIDENTIAL.
-server KNOWN
-client IGNORE

A JetBrains IDEA bundled JDK typicaly contains:

-server KNOWN
-client ALIASED_TO -server

Step 3: Dynamic Library Resolution

The loaded configuration directs the JVM to locate jvm.dll—the core implementation library for the Java Virtual Machine. This DLL contains the native code implementing core VM functionality including memory management, thread scheduling, and bytecode interpretation.

Step 4: Environment Initialization

Upon loading jvm.dll, the VM initializes its internal structures and obtains critical interface pointers, most notably the JNIEnv interface. This interface provides the native code bridge between Java and the underlying operating system, enabling operations such as class loading (findClass) and method invocation.

Step 5: Application Entry

Using the initialized interfaces, the JVM locates the main method within the specified class. From this point, bytecode execution begins and the application takes control of the runtime.


JVM Runtime Architecture

Escape Analysis and Stack Allocation

Traditional JVM memory management allocates all object instances on the heap, even objects with method-local scope. The JVM's escape analysis optimization detects objects that never escape their declaring method—meaning the reference is never exposed to external scopes or other threads.

Optimization mechanism: When the JIT compiler identifies a non-escaping object, it allocates the object's memory directly on the stack rather than the heap. The object remains valid throughout the method's execution on the call stack. When the method returns, its stack frame is destroyed, automatically reclaiming the object's memory without requiring garbage collection.

Performance implication: Benchmarks demonstrate that workloads running with escape analysis enabled achieve approximately six times the throughput compared to identical workloads running without this optimization. This improvement stems from reduced heap allocation pressure and decreased GC pause frequency.

The optimization is transparent to the application developer—JVM-level analysis handles object eligibility determination. Without escape analysis active, manual code-level optimizations yield minimal benefit since the JVM still allocates objects on the heap.

Enabling escape analysis: Requires JDK 1.6.0_14 or higher. Activation uses the -XX:+DoEscapeAnalysis flag. Disabling uses -XX:-DoEscapeAnalysis.

Stack Allocation Requirements

  • Object size constraint: Only small objects—typically ranging from a few dozen bytes—qualify for stack allocation. The stack's limited size (generally capped around 1MB) cannot accommodate large allocations.
  • Scope requirement: The object reference must not escape the declaring method. Any exposure to external scopes, other threads, or method returns invalidates stack allocation eligibility.
  • Automatic memory recovery: Because stack-allocated objects are bound to their frame's lifetime, memory reclamation happens automatically upon method return. This eliminates the need for garbage collection of temporary objects.
  • Exclusion criteria: Objects referenced by other threads, stored in static fields, returned as method results, or exceeding size thresholds cannot receive stack allocation, even when escape analysis optimization is enabled.

GC Logging Interpretation

Understanding garbage collection output provides visibility into memory management behavior:

GC Event Format: DefNew: 6972K->431K(9216K)

  • DefNew indicates the garbage collector ran in the young generation (new/tenured generation boundary)
  • 6972K->431K represents memory usage before and after collection
  • (9216K) specifies the total capacity of that memory region

Heap region terminology:

Region Description
Def new generation Young generation containing Eden space and Survivor spaces, where new object allocations occur
Tenured generation Old generation holding objects surviving multiple minor GC cycles
Compacting perm gen Non-heap permanent generation storing class metadata and static references

Reference: https://yq.aliyun.com/articles/49201

Tags: JVM java Memory Management escape analysis garbage collection

Posted on Sun, 17 May 2026 12:01:01 +0000 by ytse