Virtual Memory

[!NOTE] This module explores the core principles of Virtual Memory, deriving solutions from first principles and hardware constraints to build world-class, production-ready expertise.

1. The Great Lie: Virtual Memory

If you write a simple program that prints the memory address of a variable, you might see something like 0x7ffcd3e1. If you run two instances of that same program simultaneously, they might both print 0x7ffcd3e1.

How can two different programs store data at the same address without overwriting each other?

The answer is Virtual Memory. The OS is lying to your process.

  • The Illusion: Every process believes it has access to a contiguous, private memory space (e.g., 256TB on 64-bit systems), starting from 0x00... to 0xFF....
  • The Reality: Your computer only has 16GB of Physical RAM. The OS scatters your data across random physical frames and even on the disk (Swap).

Why Do We Need This Illusion?

  1. Isolation (Safety): Process A cannot calculate the physical address of Process B. It can only see its own virtual sandbox. If it tries to access an unmapped address, the CPU raises a Segmentation Fault.
  2. Multitasking: You can run 10 programs that each think they are using address 0x1000. The OS maps them to 0x5000, 0x9000, 0xB000, etc., in physical RAM.
  3. Efficiency: You can run a game that requires 100GB of assets on a 16GB machine. The OS only loads the parts currently needed (Working Set) into RAM and keeps the rest on disk.

2. The Hardware Reality: The MMU

The Memory Management Unit (MMU) is a specialized hardware chip (now integrated into the CPU) that sits between the CPU and the RAM.

Every time your code executes an instruction like MOV RAX, [0x1000], the CPU does not send 0x1000 to the RAM.

  1. CPU sends Virtual Address (VA) 0x1000 to the MMU.
  2. MMU looks up the translation in the Page Table (stored in RAM).
  3. MMU finds that Virtual Page 0x1 maps to Physical Frame 0x5.
  4. MMU sends Physical Address (PA) 0x5000 to the RAM.
  5. RAM returns the data.

The Cost of Translation

This lookup happens for every single memory access. Instructions, variables, stack pushes—everything goes through the MMU. To make this fast, the MMU uses a cache called the TLB (Translation Lookaside Buffer).

  • TLB Hit: Translation happens in ~1 CPU cycle.
  • TLB Miss: The MMU has to “walk” the Page Table in RAM, costing ~100+ cycles.

3. Interactive: The MMU Translator

Act as the MMU. Translate the Virtual Address (VA) to the Physical Address (PA) using the mapping provided.

CPU (Virtual)

Request: 0x1000
Process View
MMU
TLB Lookup...

RAM (Physical)

Access: ???
Hardware View

Active Page Table

0x1000 → 0x5000 0x2000 → 0x9000 0x3000 → FAULT
Ready.

4. Code Example: Address Space Proof

We will allocate a variable in two different languages. Notice how the pointers look like “normal” numbers, but they are actually Virtual Addresses that the MMU will intercept.

[!NOTE] In Go, the garbage collector might move objects around, but the pointer value you see is the stable virtual address exposed to the runtime. In Java, direct memory access is usually hidden, but we can inspect object identity hashcodes or use Unsafe (for educational purposes) to peek at memory.

package main

import (
	"fmt"
	"unsafe"
)

func main() {
	// 1. Allocate a variable on the Stack
	var x int = 42

	// 2. Allocate a large array on the Heap
	// This likely requires a new Page from the OS
	data := make([]byte, 1024*1024*10) // 10MB buffer

	fmt.Printf("Virtual Address of x (Stack): %p\n", &x)
	fmt.Printf("Virtual Address of data (Heap): %p\n", &data[0])

	// We can inspect the raw pointer value
	ptr := unsafe.Pointer(&x)
	addr := uintptr(ptr)
	fmt.Printf("Raw Address Value: 0x%x\n", addr)

	// Pause to allow running a second instance
	fmt.Println("Press Enter to exit...")
	fmt.Scanln()
}
public class AddressSpace {
    public static void main(String[] args) {
        // Java hides pointers, but Object.hashCode() is often
        // derived from the memory address (though not guaranteed).

        Object obj = new Object();

        // This is a Virtual Address illusion maintained by the JVM
        // The JVM itself runs inside the OS's Virtual Memory.
        System.out.printf("Object Hash (Virtual Identity): %s%n",
            Integer.toHexString(System.identityHashCode(obj)));

        // To see real "Virtual Addresses", we need JNI or Unsafe.
        // But conceptually, the JVM Heap is just a large chunk
        // of Virtual Memory requested from the OS via mmap.

        byte[] largeBuffer = new byte[10 * 1024 * 1024]; // 10MB
        System.out.println("Allocated 10MB on JVM Heap.");

        System.out.println("Press Enter to exit...");
        try { System.in.read(); } catch (Exception e) {}
    }
}