Unit 3 · OOP Concepts

3.2.1Stack, heap and dynamic allocation

Stack and heap

A running program uses two main memory areas:

AreaStoresLifetime
StackLocal variables and method parameters, including local reference variables. Each method call gets its own frameFreed automatically when the method returns
HeapObjects (everything created with new), including their attributes (instance variables)Lives while it can be reached; once unreachable, the garbage collector may reclaim it
Java
Student s = new Student("Nimal", 80);

The reference variable s sits on the stack. The Student object itself sits on the heap. s holds the address of the object.

STACKframe: main()slocal variablesand parametersfreed when main() endsHEAPStudent objectname●marks80"Nimal"objects created with newlive until unreachable, then the GC frees them
The reference variable lives in the method's stack frame; the object it points to lives on the heap

How the stack works

The stack works like a pile of plates. When a method is called, a new frame is put on top of the stack. It holds the method's parameters and local variables. When the method returns, its frame is taken off, and all of its local variables disappear at once. The method that is running now is always the one at the top.

Java
public static void main(String[] args) {
    int x = 5;
    Student s = new Student("Nimal", 80);
    printTwice(x);
}

static void printTwice(int n) {
    int result = n * 2;
    System.out.println(result);
}

If a method keeps calling itself and never stops, frames pile up until the stack is full, and Java throws a StackOverflowError.

Primitive variables and reference variables

Primitive variable (int, double, boolean, ...)Reference variable (Student, String, arrays, ...)
Holds the value itselfHolds the address of an object on the heap
int b = a; copies the value; the two are independentStudent t = s; copies the address; both refer to the same object
Cannot be nullCan be null (refers to no object)

Passing objects to methods

Java always passes a copy of the argument. For a primitive that is a copy of the value, so the method cannot change the caller's variable. For an object it is a copy of the reference, so the method can change the object that both references point to:

Java
static void addBonus(Student st) { st.marks = st.marks + 5; }

Student s = new Student("Nimal", 80);
addBonus(s);
System.out.println(s.marks);   // 85: the same object was changed

Dynamic memory allocation

Dynamic allocation means memory is requested while the program runs, with a size that may not be known beforehand.

Java
int[] marks = new int[n];                 // size decided at run time
Student[] list = new Student[30];         // 30 references, all null
list[0] = new Student("Nimal", 80);       // objects created on demand

null means a reference points to no object. Calling a method on null throws a NullPointerException.

Memory problems in C++, and how Java avoids them

ProblemWhat happens in C++Java
Memory leakMemory from new is never released with delete. The program uses more and more memoryThe garbage collector frees unreachable objects
Dangling pointerMemory is used after delete. The program may crash, or read rubbishThere is no delete, so this cannot happen
Double deleteThe same memory is freed twice, which corrupts memoryCannot happen

Java trades a little control (you cannot choose when memory is freed) for a lot of safety.

Remember

  • The stack holds method frames with local variables; it is cleaned up automatically when each method returns.
  • The heap holds objects; a reference variable holds the object's address.
  • Copying a reference does not copy the object, and a method that receives a reference can change the object.