0% found this document useful (0 votes)
33 views

Chapter 7 Objects and Memory

The document discusses memory structures in Java including the heap, stack, and pointers. It explains that objects are stored in the heap and referenced by pointers on the stack. When a method is called, a new stack frame is created to hold local variables and parameters. The document provides examples of stack-heap diagrams that visualize how memory is allocated and objects are referenced during method calls and object creation.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views

Chapter 7 Objects and Memory

The document discusses memory structures in Java including the heap, stack, and pointers. It explains that objects are stored in the heap and referenced by pointers on the stack. When a method is called, a new stack frame is created to hold local variables and parameters. The document provides examples of stack-heap diagrams that visualize how memory is allocated and objects are referenced during method calls and object creation.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 25

Chapter 7 Objects and Memory

Structure of memory
The fundamental unit of memory is called a bit, either 0 or 1. In most modern architectures, the smallest unit on which the hardware operates is a sequence of eight consecutive bits called byte. a binary (executable) file 0 1 2 3 010110011000010010011110110000011... Numbers and instructions are stored in still larger units. The most common integer size on a particular hardware is called a word. Because machines have different architectures, the number of bytes and the order of bytes in a word may vary from machine to machine.

Numbers, bases, and conversion


2110 = 101012 0.6562510 = 0.101012 Octal (0,1,2,3,4,5,6,7) 101012 = 0101012 = 258 0.101012 = 0.1010102 = 0.528 Hexadecimal (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F) 101012 = 000101012 = 1516 0.101012 = 0.101010002 = 0.A816 Useful numbers 100000000002 = 102410 (about 1K)

Memory allocation of variables


LOW code and static data objects (heap)

local variables (stack) HIGH

Memory allocation to variables


One region of memory is reserved for static data, variables that are never created or destroyed as the program runs, such as named constants and other class variables. When a new object is created, Java allocates space from a pool f memory called the heap. Each time a method is called, Java allocates a new block of memory called a stack frame to hold its local variables. When the method returns, its stack frame is erased. Stack frames come from a region of memory called the stack. In classical architectures, the stack and heap grow toward each other for flexibility.

Heap-stack diagrams
It is easier to understand how Java works if you have a good mental model of its use of memory. Whenever your program creates a new object, you need to add a block of memory to the heap. That block must be large enough to store the instance variables for the object, along with some extra space called overhead, that is required for any object. Whenever your program calls a method, you need to create a new stack frame by adding a block of memory to the stack region. The stack frame must be large enough to store local variables for the method, along with some overhead. When a method returns, Java reclaims the memory in its frame.

Object references
Internally, Java identifies an object by its address in memory. That address is called a reference. As an example, when Java evaluates the declaration
Rational a = new Rational(1, 2)

it allocates heap space for the new Rational object. For this example, imagine that the object is allocated at address 1000. The local variable a is allocated in the current stack frame and is assigned the value (address), which identifies the object.

heap

Address model
a.num a.den 1 2

1000

1020
public void run() { Rational a = new Rational(1, 2); Rational b = new Rational(1, 3); Rational c = new Rational(1, 6); Rational sum = (a.add(b)).add(c); } b.num b.den 1 3

1040
c.num 1 6 FFB4 1040 FFB8 FFBC FFC0 stack

c.den
sum c

b
a

1020
1000

heap

Pointer model
a.num a.den 1 2

public void run() { Rational a = new Rational(1, 2); Rational b = new Rational(1, 3); Rational c = new Rational(1, 6); Rational sum = (a.add(b)).add(c); }

b.num b.den

1 3

c.num

1 6

c.den
sum c

b
a stack

heap

public void run() { Rational a = new Rational(1, 2); Rational b = new Rational(1, 3); Rational c = new Rational(1, 6); Rational sum = (a.add(b)).add(c); }
public Rational add(Rational r) { return new Rational(this.num*r.den + r.num*this.den, this.den*r.den); }

1000 a.num a.den 1 2 1020 b.num b.den 1 3 1040 c.num 1 6

r this

1020 1000

FFA8 FFAC

c.den

sum
c b a 1040 1020 1000

FFB4
FFB8 FFBC FFC0

stack

heap

public void run() { Rational a = new Rational(1, 2); Rational b = new Rational(1, 3); Rational c = new Rational(1, 6); Rational sum = (a.add(b)).add(c); }
public Rational add(Rational r) { return new Rational(this.num*r.den + r.num*this.den, this.den*r.den); }

1000 a.num a.den 1 2 1020 b.num b.den


1

3 1040

c.num

1 6 1060

c.den

sum
c b a 1040 1020 1000

FFB4
FFB8 FFBC FFC0 stack

(a.add(b)).num (a.add(b)).den

5 6

heap

public void run() { Rational a = new Rational(1, 2); Rational b = new Rational(1, 3); Rational c = new Rational(1, 6); Rational sum = (a.add(b)).add(c); }
public Rational add(Rational r) { return new Rational(this.num*r.den + r.num*this.den, this.den*r.den); }

1000 a.num a.den 1 2 1020 b.num b.den 1 3 1040 c.num 1 6 1060


(a.add(b)).num (a.add(b)).den

r this

1040 1060

FFA8 FFAC

c.den

sum
c b a 1040 1020 1000

FFB4
FFB8 FFBC FFC0 stack

5 6 1080

(a.add(b)).add(c).num (a.add(b)).add(c).den

1
1

heap

public void run() { Rational a = new Rational(1, 2); Rational b = new Rational(1, 3); Rational c = new Rational(1, 6); Rational sum = (a.add(b)).add(c); }
public Rational add(Rational r) { return new Rational(this.num*r.den + r.num*this.den, this.den*r.den); }

1000 a.num a.den 1 2 1020 b.num b.den 1 3 1040 c.num 1 6 1060

c.den

sum

1080
1040 1020 1000

FFB4
FFB8 FFBC FFC0 stack

(a.add(b)).num (a.add(b)).den

5 6 1080

c b a

(a.add(b)).add(c).num (a.add(b)).add(c).den

1
1

heap

public void run() { Rational a = new Rational(1, 2); Rational b = new Rational(1, 3); Rational c = new Rational(1, 6); Rational sum = (a.add(b)).add(c); }
public Rational add(Rational r) { return new Rational(this.num*r.den + r.num*this.den, this.den*r.den); }

1000 a.num a.den 1 2 1020 b.num b.den 1 3 1040 c.num 1 6 1060

c.den

sum

1080
1040 1020 1000

FFB4
FFB8 FFBC FFC0 stack

(a.add(b)).num (a.add(b)).den

5 6 1080

c b a

(a.add(b)).add(c).num (a.add(b)).add(c).den

1
1

Garbage collection
In the previous example, the object a.add(b) was created in the intermediate step but not referenced by the final stack. It is now garbage. When memory is running short, Java does garbage collection
Mark the objects referenced by variables on stack or in static storage. Sweep all objects in the heap, reclaim unmarked objects (garbage).

This process is called garbage collection (mark-andsweep collector).

Exercise: Stack-heap diagram


public class Point { public Point(int x, int y) { cx = x; cy = y; } private int cx; private int cy; } } public void run() { Point p1 = new Point(0, 0); Point p2 = new Point(200, 200); Line line = new Line(p1, p2); } public class Line { public Line(Point p1, Point p2) { start = p1; finish = p2; } private Point start; private Point finish;

Draw a heap-stack diagram (pointer model) showing the state of memory just before the run() method returns.

Primitive type versus objects


Primitive type
public void run() { int x = 17; increment(x); println(x = + x); }

private void increment(int n) { n++; println(n = + n); }


Output n = 18 n = 17

When you pass an argument of a primitive type to a method, Java copies the value of the argument into the parameter variable. As a result, changes to the parameter variable have no effect on the argument.

Passing x of primitive type int, a value


increment(x);

n x

17 17

FFC0 FFC8

x (a value) is copied into n

EmbeddedInteger class
public class EnbeddedInteger { public EmbeddedInteger(int n) { value = n; } public void setValue(int n) { value = n; } public int getValue() { return value; } public String toString() { return + value; } private int value; }

Object
public void run() { EmbeddedInteger x = new EmbeddedInteger(17); increment(x); println(x = + x); } private void increment(EmbeddedInteger n) { n.setValue(n.getValue() + 1); println(n = + n); } Output n = 18 n = 18

Primitive types vs objects


When you pass an object as an argument, there seems to be some form of sharing going on. However, any changes that you make to the instance variables inside an object have a permanent effect on the object. Stack-heap diagrams make the reason for this seeming asymmetry clear. When you pass an object to a method, Java copies the reference, not the object itself.

Passing object x, a reference (address)


increment(x)
heap
n

stack
1000 FFC0

1000
x.value 17

1000

FFC8

x (a reference to an object) is copied into n x and n share the same object

Wrapper classes
byte short int long float double boolean char Byte Short Integer Long Float Double Boolean Character

Using wrapper classes


You can create an instance of a wrapper class by calling its constructor with the primitive value. For example, Integer five = new Integer(5); creates a new Integer object containing the value 5. For each of the wrapper classes, Java defines a method to retrieve the primitive value, as illustrated below: int underlyingValue = five.intValue();

Boxing and unboxing


As of Java Standard Edition 5.0, Java automatically converts values back and forth between a primitive type and the corresponding wrapper class. For example, if you write Integer five = 5; Java will automatically call the Integer constructor. Similarly, if you then write int six = five + 1; Java will automatically call intValue before the addition. These operations are called boxing and unboxing. Although boxing and unboxing can be quite convenient, this feature can generate confusion and should be used with care.

You might also like