Java objects normally live on the heap, while variables, fields, arrays, and runtime structures hold references that let the JVM find and use those objects.

Learning Question

When Java code creates an object, where is the object and what is the variable holding?

At the source level, this line looks simple:

User user = new User();

At runtime, the new User() expression allocates an object, and the variable user holds a reference to that object. The variable is not the object itself.

The first mental model is:

Objects live in heap memory. References are values that point the JVM to objects.

Object Allocation

When bytecode creates an object, the JVM needs class metadata for the object’s type and enough heap space for the object instance.

The object stores its instance fields and runtime header information needed by the JVM. The exact layout is implementation-specific, but the practical boundary is stable: the object body is heap state, not a local variable sitting directly inside a stack frame.

HotSpot often makes allocation very fast by using thread-local allocation buffers and simple pointer movement in common cases. That implementation detail improves performance, but it does not change the core concept: ordinary objects are allocated in managed heap memory.

References

A reference is a value that lets the JVM access an object.

References can appear in many places:

  • local variable slots in stack frames
  • object fields
  • static fields
  • array elements
  • JVM internal structures
  • native references
  • optimized machine-code state

This is why object lifetime is not determined by whether one specific source variable still exists. The question is whether the object is reachable from roots through references the JVM recognizes.

Primitive Values and Reference Values

Java variables can hold primitive values or reference values.

For example:

int count = 3;
User user = new User();

count holds a primitive int value. user holds a reference value. The User object itself is elsewhere, normally on the heap.

This distinction matters when reasoning about assignment:

User a = new User();
User b = a;

This does not copy the object. It copies the reference. Both variables can refer to the same object.

Object Identity and Mutation

Objects have identity. Two references may point to the same object, and mutation through one reference can be visible through another reference if the program reaches the same object.

For example:

User a = new User();
User b = a;
a.name = "Mina";

b.name observes the same field value because a and b refer to the same object.

The JVM does not duplicate heap objects just because references are assigned. It preserves object identity unless application code explicitly creates another object.

Allocation Is Not Always Physically Simple

The conceptual model says objects are allocated on the heap. That is the right model for understanding Java semantics, references, and GC.

However, an optimizing JVM may remove or transform some allocations when it can prove the object does not need to exist as a normal heap object. Escape analysis can allow scalar replacement or other optimizations.

This is a runtime optimization detail. It should not be used as the first mental model. Start with heap allocation and object references, then remember that the JIT may optimize some cases without changing Java-visible behavior.

Reachability and Lifetime

An object can be reclaimed only when the JVM determines that it is unreachable from GC roots.

Roots include sources such as live thread stack references, static references, JNI references, and JVM internal references. The exact root set depends on the runtime situation, but the principle is stable:

GC cares about reachability, not programmer intention.

An object is not freed just because you are “done with it” in a human sense. It becomes reclaimable when no reachable path to it remains.

Core Mental Model

Keep these boundaries separate:

  • An object is heap state with fields and runtime identity.
  • A reference is a value that lets the JVM find an object.
  • Assigning a reference copies the reference, not the object.
  • Object lifetime is governed by reachability from GC roots.
  • Optimizations may remove some physical allocations, but Java-visible behavior still follows object and reference semantics.

Final Summary

Java object reasoning starts with heap objects and references.

Variables do not contain ordinary objects directly. They contain primitive values or references, and the JVM uses reachable references to decide which heap objects remain alive.