Dataslope logoDataslope

Objects in Memory

How the JVM lays out objects on the heap, what a reference really is, and why null exists

You can write a lot of Java without thinking about memory. But ten minutes of looking at how the JVM actually represents objects will clear up more confusions than any number of pages of prose. We will not go deep — just deep enough to make null, "two variables referring to the same object," and "objects passed to methods" feel obvious.

The two regions: stack and heap

When a JVM program runs, it uses (among other things) two regions of memory:

RegionWhat lives thereLifetime
StackLocal variables, method parameters, the references to objectsThe current method call
HeapThe actual objects created by newUntil no references remain (then garbage-collected)

Primitive values like int and boolean live directly on the stack as part of a local variable. Object values are different. When you write Dog d = new Dog(...), two things happen:

  1. The JVM allocates a Dog object on the heap.
  2. The local variable d on the stack holds a reference (an address) pointing to that heap object.

The variable d is not the dog. The variable is a small label on the stack that says "the dog you want is at this address on the heap."

Two variables can point to the same object

This is where most beginners get a surprise. If you copy an object variable into another variable, you copy the reference, not the object itself. Both variables now point at the same heap object.

Code Block
Java 8 (Update 492)

The == operator on object types checks reference identity: do both variables point to the same heap object? It does not check whether the contents are equal. (For content equality you call .equals(...), which we'll meet later.)

A new object is a different object — even with the same contents

Code Block
Java 8 (Update 492)

Two Dog objects, two heap allocations, two distinct identities. a == c is false even though both dogs are named "Rex." Identity matters in OOP: an object is not just a bag of data, it is a specific thing.

null: a reference that points to nothing

What if a reference variable doesn't yet point to any object? Java gives it the special value null. A reference variable is either an arrow into the heap, or it is null.

Trying to send a message to null produces a NullPointerException — the JVM's way of saying "you asked nothing to do something."

Code Block
Java 8 (Update 492)

Avoid null when you can

null is convenient but dangerous. Modern Java code tries hard to avoid null for "no value here" — preferring constructors that never produce a half-built object, default values, and java.util.Optional. We will see those techniques later.

Passing objects to methods: still references

When you pass an object to a method, you pass the reference. The method receives a new local variable (on its own stack frame) that points at the same heap object as the caller's variable. Changes the method makes to the object's fields are therefore visible to the caller.

Code Block
Java 8 (Update 492)

But re-assigning the parameter to a new object does not affect the caller, because the parameter is its own local variable.

Code Block
Java 8 (Update 492)

That subtle difference — mutating the pointed-to object vs. reassigning the local reference — is the source of a lot of bugs in beginner Java code. Look at every method that takes an object and ask: "Does this method mutate the object, or just look at it?" The answer affects everything.

Object lifecycle: from new to garbage collection

You never manually free a Java object. The JVM's garbage collector notices when an object has no remaining references and reclaims its memory. This is one of Java's defining design choices. It removes a huge class of bugs (use-after-free, double-free, memory leaks from forgotten free calls) at the cost of a small amount of background work at runtime.

A picture of an object graph

Real programs build graphs of objects on the heap: a Person that references an Address, which is itself an object; a Library that references many Book objects; an Order that references a Customer and a list of LineItems. The whole point of OOP is that the heap ends up looking like a small map of your problem domain.

When you draw a diagram like this for the program you are writing, you are not "doing math" — you are seeing the system. We will draw many of them.

Test your understanding

QuestionSelect one

Given Dog a = new Dog("Rex"); Dog b = a;, how many Dog objects exist on the heap?

Zero

One — both a and b are references to the same object

Two — Java duplicates on assignment

It depends on the garbage collector

QuestionSelect one

What is a NullPointerException?

An error from running out of heap memory

An error from invoking a method or accessing a field on a reference whose value is null

An error from overflowing the call stack

An error from dividing by zero

QuestionSelect one

If a method parameter Dog dog is reassigned inside the method (dog = new Dog(...)), what happens to the caller's variable?

The caller's variable also points to the new object

The original object is freed immediately

The caller's variable still points at the original object — only the local parameter changed

The program throws a NullPointerException

On this page