0% found this document useful (0 votes)
7 views36 pages

Life and Death of An Object

The document explains memory management in Java, focusing on the stack and heap. It details how methods are executed using stack frames, the lifecycle of local and instance variables, and the concept of constructor chaining in object-oriented programming. Additionally, it discusses the lifespan of variables and objects, emphasizing the importance of scope and garbage collection.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views36 pages

Life and Death of An Object

The document explains memory management in Java, focusing on the stack and heap. It details how methods are executed using stack frames, the lifecycle of local and instance variables, and the concept of constructor chaining in object-oriented programming. Additionally, it discusses the lifespan of variables and objects, emphasizing the importance of scope and garbage collection.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 36

Life and Death

of an Object
COMP2396 Object-Oriented Programming and Java
Dr. Kenneth Wong
The Stack and the Heap
 In Java, we care about 2 areas of memory, namely the stack
and the heap

 The stack
 Memory set aside as a scratch space for a thread of execution
 Used to store method invocations and local variables
 Last-In-First-Out (LIFO)

 The Heap
 Memory set aside for dynamic allocation
 Also known as the garbage-collectible heap
 Where all objects live

1
Methods are Stacked
 When a method is called, a new stack frame is created and
pushed onto the top of the stack
 A stack frame holds the state of the method, including which
line of code is executing and the values of all local variables
 The method at the top of the stack is always the currently
running method for that stack
 A method stays on the stack until it hits its closing curly
brace top of stack
stack
 Example frames
bar() s

 If foo() calls bar(), bar() is foo() x i b


local
stacked on the top of foo() variables

bottom of stack
2
A Stack Scenario
 Example
public void doStuff() { 1 Code from another class calls
boolean b = true; doStuff(), and doStuff() goes
go(4); into a stack frame at the top of
} the stack. The boolean
variable named ‘b’ goes on the
public void go(int x) { doStuff() stack frame
int z = x + 24;
crazy();
// imagine more code here
}

public void crazy() { doStuff() b


char c = 'a';
}

3
A Stack Scenario
 Example
public void doStuff() { 2 doStuff() calls go(), go() is
boolean b = true; pushed on top of the stack.
go(4); Variables ‘x’ and ‘z’ are on the
} go() stack frame

public void go(int x) {


int z = x + 24;
crazy();
// imagine more code here
}
go() x z

public void crazy() { doStuff() b


char c = 'a';
}

4
A Stack Scenario
 Example
public void doStuff() { 3 go() calls crazy(), crazy() is
boolean b = true; now on the top of the stack,
go(4); with variable ‘c’ on the frame
}

public void go(int x) {


int z = x + 24;
crazy();
// imagine more code here crazy() c

}
go() x z

public void crazy() { doStuff() b


char c = 'a';
}

5
A Stack Scenario
 Example
public void doStuff() { 4 crazy() completes, and its
boolean b = true; stack frame is popped off the
go(4); stack. Execution goes back to
} the go() method, and picks up
at the line following the call to
public void go(int x) { crazy()
int z = x + 24;
crazy();
// imagine more code here
}
go() x z

public void crazy() { doStuff() b


char c = 'a';
}

6
Local Variables for Objects
 Remember, a non-primitive variable holds a reference to an
object, but not the object itself
 For a local variable holding a reference to an object, only the
variable goes on the stack, the object still lives on the heap
 Example
public class StackRef { barf() declares a reference variable
public void foof() { ‘d’ and creates a new Duck object.
barf(); Since ‘d’ is declared inside the
method, it is a local variable and goes
}
on the stack Duck
object
public void barf() {
Duck d = new Duck(24);
barf() d
}
The Duck object
} foof() lives on the heap

7
Instance Variables
If local variables live on the stack,
where do instance variable live?

 Instance variables live inside the object they belong to, and
therefore they also live on the heap
 Example
public class CellPhone {
priavte int x; x ant

private Antenna ant; int Antenna


}
CellPhone
object
When a CellPhone object is created,
its instance variables ‘x’ and ‘ant’ live
inside the object on the heap
8
Instance Variables
If local variables live on the stack,
where do instance variable live?

 Instance variables live inside the object they belong to, and
therefore they also live on the heap
Antenna
 Example object

public class CellPhone {


All objects live on the
priavte int x; x ant
heap, regardless of
private Antenna ant = new Antenna(); int Antenna whether the reference
} is a local or instance
CellPhone variable
object
When a CellPhone object is created,
its instance variables ‘x’ and ‘ant’ live
inside the object on the heap
9
The Role of Superclass Constructors
 Recall that every object holds not just its own declared
instance variables, but also everything from its superclasses
 Conceptually, an object can be thought of as having layers
of itself representing each superclass and its own class
 Note that private instance variables in
a superclass, though not inherited by
a subclass object, also forms part of
the superclass part of the object Object

 A subclass object might inherit methods Animal


that depend on private instance variables Hippo
of the superclass!

10
The Role of Superclass Constructors
 When an object is being created, all the constructors
(including those of the abstract classes) up the inheritance
tree must run to build out both the superclass parts and its
own class part of the object

 When a constructor runs, it immediately calls its superclass


constructor, which in turn immediately calls its superclass
constructor…

 This calling of superclass constructor will go all the way up


the hierarchy until the Object class constructor is reached

 This process is known as constructor chaining

11
Constructor Chaining
 Example
public abstract class Animal {
public Animal() { Object
System.out.println("Making an Animal");
}
}

public class Hippo extends Animal {


Animal
public Hippo() {
System.out.println("Making a Hippo");
}
}

public class TestHippo { Hippo


public static void main(String[] args) {
System.out.println("Starting...");
Hippo h = new Hippo();
}
} 12
Constructor Chaining
 Example
public abstract class Animal { 1 The main() in the TestHippo
public Animal() { class says new Hippo() and the
System.out.println("Making an Animal"); Hippo() constructor goes into a
} stack frame at the top of the
} stack

public class Hippo extends Animal {


public Hippo() {
System.out.println("Making a Hippo");
}
}

public class TestHippo {


public static void main(String[] args) { Hippo()
System.out.println("Starting...");
Hippo h = new Hippo();
}
} 13
Constructor Chaining
 Example
public abstract class Animal { 2 Hippo() invokes the superclass
public Animal() { constructor which pushes the
System.out.println("Making an Animal"); Animal() constructor onto the
} top of the stack
}

public class Hippo extends Animal {


public Hippo() {
System.out.println("Making a Hippo");
}
}
Animal()
public class TestHippo {
public static void main(String[] args) { Hippo()
System.out.println("Starting...");
Hippo h = new Hippo();
}
} 14
Constructor Chaining
 Example
public abstract class Animal { 3 Animal() invokes the
public Animal() { superclass constructor which
System.out.println("Making an Animal"); pushes the Object()
} constructor onto the top of the
} stack (Object is the superclass
of Animal!)
public class Hippo extends Animal {
public Hippo() {
System.out.println("Making a Hippo");
}
} Object()
Animal()
public class TestHippo {
public static void main(String[] args) { Hippo()
System.out.println("Starting...");
Hippo h = new Hippo();
}
} 15
Constructor Chaining
 Example
public abstract class Animal { 4 Object() completes, and its
public Animal() { stack frame is popped off the
System.out.println("Making an Animal"); stack. Execution goes back to
} the Animal() constructor, and
} picks up at the line following
Animal’s call to its superclass
public class Hippo extends Animal { constructor
public Hippo() {
System.out.println("Making a Hippo");
}
}
Animal()
public class TestHippo {
public static void main(String[] args) { Hippo()
System.out.println("Starting...");
Hippo h = new Hippo();
}
} 16
Constructor Chaining
 Example  Sample output
public abstract class Animal { Starting...
public Animal() { Making an Animal
System.out.println("Making an Animal"); Making a Hippo
}
}

public class Hippo extends Animal {


public Hippo() {
System.out.println("Making a Hippo");
}
}

public class TestHippo {


public static void main(String[] args) {
System.out.println("Starting...");
Hippo h = new Hippo();
}
} 17
Child Cannot Exist Before Parents
 Remember, a subclass object might depend on things it
inherits from its superclass
 Hence, the superclass parts of an object have to be fully
formed before the subclass part can be constructed
 This implies the superclass constructor must finish before its
subclass constructor
 The call to super() must therefore be the first statement in
each constructor!
 The complier will put a call to super() as the first statement
in each of your overloaded constructors if you have not done
so!

18
Child Cannot Exist Before Parents
 Example: Identify problems in the constructors
public Ball() { super(); }
No problem. The first
statement being an
explicit call to super()
public Ball(int i) { super(); size = i; }

public Ball() {}
No problem. The compiler
will put a call to super() as
the first statement
public Ball(int i) { size = i; }

public Ball(int i) { size = i; super(); } This won’t compile!


Cannot explicitly put a call to
super() below anything else
19
Invoking an Overloaded Constructor
 It is possible to call a constructor from another overloaded constructor
in the same class using this() with appropriate arguments

 The call to this() can only be used in a constructor, and must be the
first statement in a constructor

 A constructor can have a call to either super() or this(), but never


both!

 Example
import java.awt.Color;
class MiniCooper extends Car {
public MiniCooper() { this(Color.RED); }
public MiniCooper(Color color) {
super("Mini Cooper");
this.color = color;
// more initialization
}
}
20
How Long Does a Variable Live?
 How long does a variable live depends on whether the
variable is a local variable or an instance variable
 A local variable is alive as long as its stack frame is on
the stack. In other words, until the method completes
 A local variable is in scope only within the method in
which it is declared
 When its own method calls another, the variable is
alive, but not in scope until its method resumes
 The variable can only be used when it is in scope

21
The Difference between Life & Scope
 Example
public void doStuff() { 1 doStuff() goes into a stack
boolean b = true; frame at the top of the stack.
go(4); Variable ‘b’ is alive and in
} scope

public void go(int x) {


int z = x + 24;
crazy();
// imagine more code here
}

public void crazy() { doStuff() b


char c = 'a';
}

22
The Difference between Life & Scope
 Example
public void doStuff() { 2 go() is pushed on top of the
boolean b = true; stack. Variables ‘x’ and ‘z’ are
go(4); alive and in scope, and ‘b’ is
} alive but not in scope.

public void go(int x) {


int z = x + 24;
crazy();
// imagine more code here
}
go() x z

public void crazy() { doStuff() b


char c = 'a';
}

23
The Difference between Life & Scope
 Example
public void doStuff() { 3 crazy() is pushed on top of the
boolean b = true; stack, with ‘c’ now alive and in
go(4); scope. The other 3 variables
} are alive but out of scope

public void go(int x) {


int z = x + 24;
crazy();
// imagine more code here crazy() c

}
go() x z

public void crazy() { doStuff() b


char c = 'a';
}

24
The Difference between Life & Scope
 Example
public void doStuff() { 4 crazy() completes and is
boolean b = true; popped off the stack, so ‘c’ is
go(4); out of scope and dead. When
} go() resumes where it left off,
‘x’ and ‘z’ are both alive and
public void go(int x) { back in scope. Variable ‘b’ is
int z = x + 24; still alive but out of scope
crazy();
// imagine more code here
}
go() x z

public void crazy() { doStuff() b


char c = 'a';
}

25
How Long Does a Variable Live?
What about instance variables?
 An instance variable lives as long as the object does,
and is scoped to the life of the object
 In other words, instance variables live and die with the
object they belong
What about reference variable?
 The rules are the same for primitives and references
 A reference variable can be used only when it is in
scope

26
How Long Does an Object Live?
 An object is alive as long as there are live references to
it
 If a reference variable goes out of scope but is still
alive, the object it refers to is still alive on the heap
 If the stack frame holding a reference gets popped off
the stack and that is the only live reference to the
object, the object is now abandoned on the heap and
becomes eligible for garbage collection
 More precisely, an object becomes eligible for garbage
collection when its last live reference disappears

27
How Long Does an Object Live?
 3 ways to get rid of an object’s reference
 The reference variable goes out of scope permanently
void go () { The reference ‘z’ dies at
Life z = new Life(); the end of the method
}

 The reference variable is assigned another object


Life z = new Life(); The first object is abandoned when ‘z’ is
z = new Life(); ‘re-programmed’ to a new object

 The reference variable is explicitly set to null


Life z = new Life();
The first object is abandoned
z = null; when ‘z’ is ‘de-programmed’

28
Example: Object Killer #1
 Example: Reference goes out of scope permanently
public class StackRef { 1 Code from another class calls
public void foof { foof(), and foof() is pushed
barf(); on top of the stack, with no
} variables declared

public void barf() {


Duck d = new Duck();
}
}

foof()

29
Example: Object Killer #1
 Example: Reference goes out of scope permanently
public class StackRef { 2 foof() calls barf(), and barf()
public void foof { is pushed on top of the stack.
barf(); barf() declares a reference
} variable ‘d’, creates a new
Duck object on the heap, and
public void barf() { assigns its reference to ‘d’. ‘d’
Duck d = new Duck(); is alive and in scope
}
}
Duck
object

barf() d

foof()

30
Example: Object Killer #1
 Example: Reference goes out of scope permanently
public class StackRef { 3 barf() completes and is
public void foof { popped off the stack. Its stack
barf(); frame disintegrates, so ‘d’ is
} now dead and gone. The Duck
object is now abandoned and
public void barf() { becomes eligible for garbage
Duck d = new Duck(); collection. Execution returns to
} foof()
}
Duck
object

foof() eligible for garbage


collection

31
Example: Object Killer #2
 Example: Assign the reference to another object
public class ReRef { 1 The new Duck object goes on
Duck d = new Duck(); the heap and is referenced by
the instance variable ‘d’. The
public void go() { Duck object will live as long as
d = new Duck(); the ReRef object that
} instantiated it is alive, unless…
}

Duck
object

Duck

ReRef object
32
Example: Object Killer #2
 Example: Assign the reference to another object
public class ReRef { 2 Someone calls go() where ‘d’
Duck d = new Duck(); is assigned a new Duck
object, leaving the first Duck
public void go() { object abandoned which
d = new Duck(); becomes eligible for garbage
} collection
}
eligible for garbage
collection

Duck
object

Duck Duck
object
ReRef object
33
Example: Object Killer #3
 Example: Explicitly set the reference to null
public class ReRef { 1 The new Duck object goes on
Duck d = new Duck(); the heap and is referenced by
the instance variable ‘d’. The
public void go() { Duck object will live as long as
d = null; the ReRef object that
} instantiated it is alive, unless…
}

Duck
object

Duck

ReRef object
34
Example: Object Killer #3
 Example: Explicitly set the reference to null
public class ReRef { 2 Someone calls go() where ‘d’
Duck d = new Duck(); is set to null, leaving the Duck
object abandoned which
public void go() { becomes eligible for garbage
d = null; collection
}
}
eligible for garbage
collection

Duck
object

Duck

ReRef object
35

You might also like