Summary

The one connection that explains all of thread-safety

Thread-safety isn’t a separate topic — it’s a direct consequence of the JVM
memory model
you already documented years ago. Where a variable lives
decides whether it’s safe.

Hook: Stack = private per thread (safe). Heap + Method Area = shared (danger).

The split (from your JVM Architecture note)

One PC Register, JVM Stack, and Native Method Stack are created per thread.
Heap, Method Area, and Runtime Constant Pool are shared by all threads.

JVM regionPrivate / SharedHoldsThread-safety
JVM Stack (per thread)Privatelocal variables, method frameslocals always safe ✅
Heap (one)Sharedall objects (singleton fields, instance vars of shared objects)race risk ⚠️
Method Area / Metaspace (one)Sharedclass metadata, static variables, constant poolrace risk ⚠️

So the whole rule reduces to one question

“Can more than one thread reach this variable?”

  • Local variable → lives on my stack → no → safe, always.
  • static field → lives in the shared Method Area → yes → guard it.
  • Field of a shared object (singleton bean) → lives on the shared Heap → yes → guard it.
  • Field of an object I new-ed locally and never published → on the Heap, but
    only I hold the reference → safe (until you share the reference).

PermGen → Metaspace (Java 8) — common interview Q

  • Before Java 8: Method Area = PermGen, fixed-ish size (~64MB default),
    famous OutOfMemoryError: PermGen space.
  • Java 8+: replaced by Metaspace, moved to native memory, grows
    unbounded by default. Tune with -XX:MaxMetaspaceSize.

Test Yourself

See also