Memory Layout of a Process
C++
PROCESS MEMORY LAYOUT
Heap
/\
High Memory Address | | Data Segment |
┌────────────┬──────────────┬──────────────┬─────|──────┬──────────────┬──────────────┬──────────────┐
│ Kernel │ Stack │ Shared Libs │ Pointer | BSS │ .data │ Text / Code │
│ space │ grows --> │ │ to Heap │ Uninitialized│ Initialized │ Read Only │
| | | | | | <-RW-><-RO-> | |
└────────────┴──────────────┴──────────────┴────────────┴──────────────┴──────────────┴──────────────┘
0x00000000
Low Memory Address
THREAD MEMORY LAYOUT
-----------------------------Process Memory layout---------------------------
-------Process Stack-----------------
[ Thread1_Stack Thread2_Stack ][ ptr-to-heap ][Data Segment][Code Segment]
Java
A Java program runs inside the JVM (one OS process). The diagram below shows the main JVM runtime data areas in the same horizontal style as the C++ layout: higher/native address regions on the left, toward executable and off-heap areas on the right. All Java threads share the heap and metaspace; each thread has its own stacks and program counter.
OS
├── JVM Process 1
│ ├── Main Thread
│ ├── User Thread 1
│ ├── User Thread 2
│ ├── GC Thread
│ ├── JIT Compiler Thread
│ └── Cleaner Thread
├── JVM Process 2
└── JVM Process 3
MEMORY LAYOUT OF 1 JVM PROCESS
main.java(main thread)
|- thread1
|- thread2
<-------------------------------------------------------------- 1 JVM PROCESS ------------------------------------------------------------------------------------>
┬─────────────────────┬──────────────────────┬──────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────┬──────────────────────┬─────────────────────────────────┐
│ Thread Stacks │ Shared Libraries │ Metaspace │ Heap (all Objects allocated here) [GARBAGE COLLECTOR run here ONLY] │ Code Cache │ Direct Memory Allocation │
│ main thread stack │ JVM + JNI │ ┌────────────────┬─────────────────────────┐ │ ┌────────────────────────────────────┬────────────────────────────────────┐ │ TEXT SEGMENT(C++) │ Eg: ByteBuffer.allocateDirect() │
│ thread1_stack │ libjvm.so │ │Class Structures│ Runtime Constant Pool │ │ │ Young Generation │ Old Generation (Tenured) │ │ Generated at runtime │ or NIO/mapped-file │
│ thread2_stack │ │ └────────────────┴─────────────────────────┘ │ │ ┌──────────┬──────────┬──────────┐ │ │ │ │ │
│ gc_thread │ │ │ │ │ Eden │Survivor0 │Survivor1 │ │ │ │ JIT Native Code (RX) │ Not garbage collected |
│ compiler threads │ │ │ │ └──────────┴──────────┴──────────┘ │ │ │ │ │
┴─────────────────────┴──────────────────────┴──────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────┴──────────────────────┴─────────────────────────────────┘
┬───────────────────────┬───────────────────────────┬─
| JVM Process 1 | JVM Process 2 | ...
|hello.java(main thread)| test.java(main thread) |
| thread1 | |
| thread2 | |
| gc thread | |
┴───────────────────────┴───────────────────────────┴─
Metaspace. Native memory (outside the Java object heap) that stores class metadata: class definitions, method bytecode, field/method tables, and the runtime constant pool. It grows as classes are loaded. Since Java 8 it replaced PermGen (which was inside the heap in older JVMs). Static field values that are object references point into the heap; the class structure itself lives in metaspace.
Heap All Objects live here— Eden, survivor
spaces, and old generation.
The heap is shared by all Java threads.
Eden: New objects are allocated in here. When
Eden fills, a minor garbage collection copies live objects into one of
two survivor spaces (S0/S1).
Old generation (tenured). if further space is
needed(from S0/S1) objects are copied old generation.
Generational layout is a JVM optimization; logically it is still one
heap, just like the C++ heap is one region even though
malloc arenas exist internally.
Why generations? Most objects are short-lived. Collecting Eden
often (cheap, small) is faster than scanning the entire heap every time.
Code cache. Memory holding machine code generated by the JIT
compiler from hot bytecode. It is executable (like the C++
.text segment) but created at runtime, not loaded fully
from disk upfront. Bytecode itself is stored as part of class metadata
in metaspace; only optimized native translations go here.
Direct memory (off-heap). Native buffers allocated outside the
Java heap — for example ByteBuffer.allocateDirect() and
some NIO/mapped-file uses. It is still inside the same JVM OS process
but not garbage-collected with ordinary objects. Limited by
-XX:MaxDirectMemorySize.
Memory management. Garbage Collector
C++ relies on scope, destructors, smart pointers, or
manual delete.
Java: Garbage collector frees heap objects; we do not free
individual objects. Metaspace and direct memory have their own lifecycle
rules.