Short answer
At runtime the JVM divides memory into the heap (shared: young + old generations), per-thread stacks, the Program Counter register, native method stacks, and native-memory areas like Metaspace and the code cache.
Explanation
Separately, the Java Memory Model (JMM, JLS Ch. 17) defines the concurrency rules: the happens-before relationship that governs when one thread's writes become visible to another. volatile, synchronized, final-field semantics, and Thread.start/join all establish happens-before edges; without them the JVM and CPU are free to reorder and cache reads/writes, causing visibility bugs.
Common mistakes
- Confusing the Java Memory Model (visibility) with memory areas (heap, stack).
- Not mentioning happens-before.