Download - Objects, Variables, Memory
Michele Van Dyne MUS 204B [email protected] https://katie.mtech.edu/classes/csci136
10 – Objects, Variables, Memory
Where Java stores stuff ◦ The Heap
◦ The Stack
◦ Breaking both
◦ Java Garbage Collector (GC)
Creating objects ◦ Copy constructors
◦ Methods creating objects
Static keyword ◦ Static methods and instance variables
Stack ◦ Where method invocations live
◦ Where local variables live
◦ A chunk of memory
Heap ◦ Where all objects live
◦ Another chunk of memory
3
Methods are “stacked” ◦ You call a method → put on top of a call stack
◦ A method stays on stack until it finishes executing
◦ Each stack frame contains:
What line it is executing
Values of all the method’s local variables
This includes parameters to the method
4
5
public void doStuff() { boolean b = true; go(4); } public void go(int x) { int z = x + 24; crazy(); } public void crazy() { char c = 'a'; }
6
public void doStuff() { boolean b = true; go(4); } public void go(int b) { int c = b + 24; crazy(); } public void crazy() { char c = 'a'; }
doStuff() boolean b → true
doStuff() boolean b → true
go() int b → 4 int c → 28
1 2
doStuff() boolean b → true
go() int b → 4 int c → 28
3
crazy() char c → 'a'
doStuff() boolean b → true
go() int b → 4 int c → 28
4
7
public class Factorial { public static long fact(long n) { if (n <= 1) return 1; return n * fact(n - 1); } public static void main(String [] args) { long result = fact(4); System.out.println("4! = " + result); } }
0! = 1 1! = 1 2! = 1 x 2 = 2 3! = 1 x 2 x 3 = 6 4! = 4 x 3 x 2 x 1 = 24
Some example factorials.
main()
fact(4) n → 4
fact(3) n → 3
fact(2) n → 2
fact(1) n → 1
8
public class Factorial { public static long fact(long n) { if (n <= 1) return 1; return n * fact(n - 1); } public static void main(String [] args) { long result = fact(4); System.out.println("4! = " + result); } }
main() fact(4) = 24
fact(4) n → 4 return 4 * fact(3)
fact(3) n → 3 return 3 * fact(2)
fact(2) n → 2 return 2 * fact(1)
fact(1) n → 1 return 1
0! = 1 1! = 1 2! = 1 x 2 = 2 3! = 1 x 2 x 3 = 6 4! = 4 x 3 x 2 x 1 = 24
Some example factorials.
0! = 1 1! = 1 2! = 1 x 2 = 2 3! = 1 x 2 x 3 = 6 4! = 4 x 3 x 2 x 1 = 24
Some example factorials.
9
public class Factorial { public static long fact(long n) { return n * fact(n - 1); } public static void main(String [] args) { long result = fact(4); System.out.println("4! = " + result); } }
main()
fact(4) n → 4
fact(3) n → 3
fact(2) n → 2
fact(1) n → 1
fact(0) n → 0
fact(-1) n → -1
fact(-2) n → -2
Exception in thread "main" java.lang.StackOverflowError at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) at Factorial.fact(Factorial.java:6) ...
Local variables live on the stack ◦ Local variables in a method
◦ Parameters passed to a method
◦ Reference variables
e.g. passing in a int [] array, a Hero object, …
Only the remote control lives on the stack
Objects live on the heap ◦ Objects instantiated with new, live on the heap
◦ Instance variables of an object
Stored as part of the object living on the heap
10
Creating an object in 3 easy steps: 1) Declare a reference variable
11
Heap
Duck myDuck
myDuck
Creating an object in 3 easy steps: 1) Declare a reference variable
2) Create an object
12
Heap
new Duck();
myDuck
Creating an object in 3 easy steps: 1) Declare a reference variable
2) Create an object
3) Link the object and the reference
13
Heap
Duck myDuck = new Duck();
myDuck
You have now consumed memory on the heap based on how much state a Duck requires (i.e. the number and type of its instance variables).
Java tracks # of variables referring to an object ◦ As soon as nobody refers to an object, its memory
can be freed ◦ Java's automatic Garbage Collector (GC) periodically
handles this for you Exactly when is up to the JVM
Enjoy it (while it lasts)
14
You're so going to have to this
yourself in data structures.
Object-killer #1 ◦ Reference goes out of scope
permanently
15
public class DuckKiller1 { public static void makeDuck() { Duck d = new Duck(); } public static void main(String [] args) { makeDuck(); while (true) { // Do something } } }
main()
main()
makeDuck()
main()
d
Heap
Heap
Object-killer #1b ◦ Variable inside curly braces
goes out of scope
16
00 public class DuckKiller1b 01 { 02 public static void main(String [] args) 03 { 04 if (args.length >= 0) 05 { 06 Duck d = new Duck(); 07 } 08 while (true) 09 { 10 // Do something 11 } 12 } 13 }
main() line 04 line 05 line 06
d
Heap
Object-killer #1b ◦ Reference goes out of scope
permanently
17
00 public class DuckKiller1b 01 { 02 public static void main(String [] args) 03 { 04 if (args.length >= 0) 05 { 06 Duck d = new Duck(); 07 } 08 while (true) 09 { 10 // Do something 11 } 12 } 13 }
main() line 04 line 05 line 06 line 07 line 08
Heap
Object-killer #2 ◦ Assign the reference to another object
18
00 public class DuckKiller2 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 System.out.println("quack!"); 06 d = new Duck(); 07 System.out.println("quack!"); 08 d = new Duck(); 09 System.out.println("quack!"); 10 } 11 }
d
Heap
main() line 04
Object-killer #2 ◦ Assign the reference to another object
19
00 public class DuckKiller2 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 System.out.println("quack!"); 06 d = new Duck(); 07 System.out.println("quack!"); 08 d = new Duck(); 09 System.out.println("quack!"); 10 } 11 }
Heap
d
main() line 04 line 05 line 06
After executing line 06, no one is referring to the first Duck object anymore. It is now subject to garbage collection.
Object-killer #2 ◦ Assign the reference to another object
20
00 public class DuckKiller2 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 System.out.println("quack!"); 06 d = new Duck(); 07 System.out.println("quack!"); 08 d = new Duck(); 09 System.out.println("quack!"); 10 } 11 }
Heap
d
main() line 04 line 05 line 06 line 07 line 08
After executing line 08, both the first and second Ducks objects can be garbage collected.
Object-killer #3 ◦ Set the reference variable to null
21
00 public class DuckKiller3 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 System.out.println("quack!"); 06 d = null; 07 System.out.println("quack!"); 08 } 09 }
main() line 04
d
Heap
Object-killer #3 ◦ Set the reference variable to null
22
00 public class DuckKiller3 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 System.out.println("quack!"); 06 d = null; 07 System.out.println("quack!"); 08 } 09 }
Heap
main() line 04 line 05 line 06
d
After executing line 06, no one is referring to the Duck object anymore. The Java garbage collector can now free up the Duck's memory.
Memory is not infinite ◦ Can't keep new’ing forever w/o getting rid of any ◦ You can buy yourself some time:
Increase memory with JVM flag: -Xmx<num>[k|m|g]
23
import java.util.*; public class HeapDeath { public static void main(String [] args) { ArrayList<Duck> list = new ArrayList<Duck>(); while (true) { Duck d = new Duck(); list.add(d); } } }
While variable d scopes out every loop, the Duck reference persists inside the ArrayList.
Memory is never freed!
24
Type Memory size (bits, 8 bits = byte)
byte 8
short 16
int 32
long 64
float 32
double 64
boolean not precisely defined
char 16
NOTE: The size of a reference variable’s remote control is JVM dependent.
But there is always overhead for the reference variable and for any instance variables inside the data type!
http://righteousit.wordpress.com/tag/tcpip/
25
00 public class HeapPuzzler 01 { 02 public static void main(String [] args) 03 { 04 Duck d = new Duck(); 05 Duck [] a = new Duck[4]; 06 for (int i = 0; i < a.length; i++) 07 a[i] = new Duck(); 08 System.out.println("quack!"); 09 a[0] = null; 10 a[1] = d; 11 System.out.println("quack!"); 12 } 13 }
After executing line # Ducks on the heap
Variable(s) that point to a Duck object
04
05
08
09
10
1 d
1 d
5 d, a[0], a[1], a[2], a[3]
4 d, a[1], a[2], a[3]
3 (d, a[1]), a[2], a[3]
Two variables that refer to the same Duck
Copy constructor ◦ A special constructor
◦ Parameter is another object of the same type
◦ Simply copies all the state of the passed in object
26
public class Duck { private String name = ""; private double weight = 0.0; public Duck(Duck other) { this.name = other.name; this.weight = other.weight; } }
A copy constructor!
An instance method can create a new object and return it
27
Hey rabbit, what do you know? “My location and my size!” Hey rabbit, what can you do? “I can draw myself.”
“I can tell if somebody clicks on me.”
“Ohh and um, well you know, I can make them there baby rabbits…”
public class Rabbit { private double x = 0.0; private double y = 0.0; private static final double size = 0.06; public Rabbit(double x, double y) { this.x = x; this.y = y; } public void draw() { StdDraw.picture(x, y, "rabbit.png"); } public boolean intersect(double x, double y) { double deltaX = (this.x - x); double deltaY = (this.y - y); return (Math.sqrt(deltaX * deltaX + deltaY * deltaY) < size); } ...
28
public Rabbit breed() { Rabbit baby = new Rabbit(this.x + (0.2 - Math.random() * 0.4), this.y + (0.2 - Math.random() * 0.4)); return baby; } public static void main(String [] args) { ArrayList<Rabbit> rabbits = new ArrayList<Rabbit>(); rabbits.add(new Rabbit(0.5, 0.5)); while (true) { for (int i = rabbits.size() - 1; i >= 0; i--) { Rabbit r = rabbits.get(i); r.draw(); if (r.intersect(StdDraw.mouseX(), StdDraw.mouseY())) rabbits.add(r.breed()); } StdDraw.show(100); } } }
29
Static methods ◦ Forbidden from using instance vars of the class
Non-static methods (instance methods) ◦ Allowed to use instance vars
A class can have: ◦ All static methods
e.g. Math class
◦ All non-static methods
◦ A mix of both
e.g. Wrapper classes like Double and Integer
30
31
Method signature Description
public static int round(float a) Round to the nearest integer
public static long round(double a)
public static int min(int a, int b) Find the minimum of two numbers
public static long min(long a, long b)
public static float min(float a, float b)
public static double min(double a, double b)
public static int abs(int a) Return absolute value of a number
public static long abs(long a)
public static float abs(float a)
public static double abs(double a)
public static double random() Get a random number in [0.0, 1.0)
public static double sqrt(double a) Take the square root of a number
A selection of the static methods in Math.java
32
public static final double E = 2.7182818284590452354; public static final double PI = 3.14159265358979323846;
/** * Don't let anyone instantiate this class. */ private Math() {}
Constants in Math.java.
The constructor of the Math class.
A private constructor. Makes it impossible to instantiate an object of type Math.
All calls via static method calls, e.g. Math.sqrt(), Math.min()
33
int x = Math.round(42.2); int y = Math.min(56, 12); int z = Math.abs(-343);
These methods don't use instance variables, so there is no specific object to call the methods on. Methods called using class name.
Math mathObj = new Math();
You can't do this since the constructor is private:
Exception in thread "main" java.lang.Error: Unresolved compilation problem: The constructor Math() is not visible
There is no persistent state in the Math object, so no need to create an object on the heap.
Static methods ◦ Cannot use non-static instance variables
34
public class Cow { private String name = ""; private double weight = 0.0; public static double getWeight() { return weight; } }
Since getWeight() is declared static, any use of a non-static instance variable results in a compile error:
Cow.java:8: non-static variable weight cannot be referenced from a static context return weight; ^
Cow cow1 = new Cow(); Cow cow2 = new Cow(); System.out.println("weight = ", Cow.getWeight());
The weight of which cow?
Static methods ◦ Cannot call non-static methods
35
public class Cow { private String name = ""; private double weight = 0.0; public double getWeight() { return weight; } public static boolean isBig() { return (getWeight() > 500.0); } }
Since isBig() is declared static, any use of a non-static instance method results in a compile error:
Cow.java:13: non-static method getWeight() cannot be referenced from a static context return (getWeight() > 500.0); ^
Static instance variable ◦ One var shared among all instances of a class
◦ Why?
Commonly used for constants
Eliminate repeated variables that are always the same
Reduce memory, doesn’t keep copies of identical objects
Track a single value related to a class type
e.g. Number of objects created for a particular class
36
public static final double PI = 3.14159265358979323846;
37
public class Cow { private String name = ""; private double weight = 0.0; private static AudioFile sound = new AudioFile("cow.wav"); public static void makeNoise() { sound.play(); } }
Normal instance variables, each Cow object has its own set of these variables.
All Cow objects share the same sound object. Only one AudioFile object is created on the heap, thus saving memory.
38
public class Cow { private String name = ""; private double weight = 0.0; private static int numCows = 0; public Cow() { numCows++; } public Cow(Cow otherCow) { this.name = otherCow.name; this.weight = otherCow.weight; numCows++; } public static int getNumCows() { return numCows; } }
No matter how many Cow objects we create, there is only ever one numCows instance variable that has a single value.
Normal instance variables, each Cow object has its own set of these variables.
Methods that only use static variables can be declared static (but don't have to be).
How your data is stored ◦ Stack
◦ Heap
◦ Garbage collector
Creating new objects ◦ Copy constructor
◦ Other methods creating new object instances
Static keyword ◦ For methods
◦ For instance variables
Heap