Jav a The Art and Science of CHAPTER

  • Slides: 16
Download presentation
Jav a The Art and Science of CHAPTER 7 ERIC S. ROBERTS An Introduction

Jav a The Art and Science of CHAPTER 7 ERIC S. ROBERTS An Introduction to Computer Science Objects and Memory Yea, from the table of my memory I’ll wipe away all trivial fond records. —William Shakespeare, Hamlet, c. 1600 Chapter 7—Objects and Memory

Memory and Addresses • Every byte inside the primary memory of a machine is

Memory and Addresses • Every byte inside the primary memory of a machine is identified by a numeric address. The addresses begin at 0 and extend up to the number of bytes in the machine, as shown in the diagram on the right. • In these slides as well as in the diagrams in the text, memory addresses appear as four-digit hexadecimal numbers, which makes addresses easy to recognize. • In Java, it is impossible to determine the address of an object. Memory addresses used in the examples are therefore chosen completely arbitrarily. • Memory diagrams that show individual bytes are not as useful as those that are organized into words. The revised diagram on the right now includes four bytes in each of the memory cells, which means that the address numbers increase by four each time. 0000 0001 0004 0008 0002 0003 000 C 0004 0010 0005 0014 0006 0018 0007 001 C 0020 0008 0024 0009 000 A 0028 . . . 000 B 002 C FFD 0 FFF 4 FFF 5 FFD 4 FFF 6 FFD 8 FFDC FFF 7 FFF 8 FFE 0 FFE 4 FFF 9 FFE 8 FFFA FFFB FFEC FFF 0 FFFD FFF 4 FFFE FFF 8 FFFF FFFC

The Allocation of Memory to Variables • When you declare a variable in a

The Allocation of Memory to Variables • When you declare a variable in a program, Java allocates space for that variable from one of several memory regions. • One region of memory is reserved for variables that are never created or destroyed as the program runs, such as named constants and other class variables. This information is called static data. • Whenever you create a new object, Java allocates space from a pool of memory called the heap. 0000 static data heap • Each time you call a method, Java allocates a new block of memory called a stack frame to hold its local variables. These stack frames come from a region of memory called the stack. • In classical architectures, the stack and heap grow toward each other to maximize the available space. stack FFFF

Heap-Stack Diagrams • It is easier to understand how Java works if you have

Heap-Stack Diagrams • It is easier to understand how Java works if you have a good mental model of its use of memory. The text illustrates this model using heap-stack diagrams, which show the heap on the left and the stack on the right, separated by a dotted line. • Whenever your program creates a new object, you need to add a block of memory to the heap side of the diagram. 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. Overhead space is indicated in heap-stack diagrams as a crosshatched box. • Whenever your program calls a method, you need to create a new stack frame by adding a block of memory to the stack side. For method calls, you need to add enough space to store the local variables for the method, again with some overhead information that tracks what the program is doing. When a method returns, Java reclaims the memory in its frame.

Object References • Internally, Java identifies an object by its address in memory. That

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 r 1 = new Rational(1, 2); it allocates heap space for the new Rational object. For this example, imagine that the object is created at address 1000. • The local variable r 1 is allocated in the current stack frame and is assigned the value 1000, which identifies the object. heap stack 1000 num den 1 1004 2 1008 r 1 1000 FFFC • The next slide traces the execution of the Test. Rational program from Chapter 6 using heap-stack model.

A Complete Heap-Stack Trace public static void main(String[] args) {{ public Rational aa ==

A Complete Heap-Stack Trace public static void main(String[] args) {{ public Rational aa == new Rational(1, 2); Rational public Rational add(Rational r) { 36 5 Rational bb == new Rational(1, 3); Rational 2 1 3 1 Rational cc == new Rational(1, 6); Rational 6); return new this. num * r. den + r. num * this. den , Rational sum. Rational( a. add(b). add(c); Rational sum == a. add(b). add(c); ); println(a ++ "" ++ bb +this. den + "" ++*ccr. den sum); println(a ++ "" == "" ++ sum); }}} 36 6 heap num den 11 22 num den 11 33 num den 11 66 num den 55 66 num den 11 11 stack 1000 1004 1008 100 C 1010 1014 1018 101 C 1020 1024 1028 102 C 1030 1034 1038 Test. Rational 1/2 ++ 1/3 ++ 1/6 == 11 1/2 All objects are created in the heap. This object is a temporary value used only during calculation. r the FFE 0 100 C 1018 this sum cc bb aa 1000 1024 1030 1018 100 C 1000 FFE 4 FFE 8 FFEC FFF 0 FFF 4 FFF 8 FFFC This stack frame is created for the add method. This stack frame is created for the main method. skip simulation

The Pointer Model • The heap-stack diagram at the lower left shows the state

The Pointer Model • The heap-stack diagram at the lower left shows the state of memory at the end of the run method from Test. Rational. • The diagram at the lower right shows exactly the same state using arrows instead of numeric addresses. This style of diagram is said to use the pointer model. heap stack 1000 num den 1 1004 2 1008 num den 1 num den 5 num den 1 2 100 C num den 1 1010 3 1014 3 1018 num den 1 101 C 6 1020 6 1024 num den 5 1028 6 102 C 1030 num den 1 1034 1 1038 sum c b a 1030 FFEC 1018 FFF 0 100 C 1000 FFF 4 FFF 8 FFFC 6 1 sum c b a

Addresses vs. Pointers • The two heap-stack diagram formats—the address model and the pointer

Addresses vs. Pointers • The two heap-stack diagram formats—the address model and the pointer model—describe exactly the same memory state. The models, however, emphasize different things: – The address model makes it clear that references have numeric values. – The pointer model emphasizes the relationship between the reference and the object and makes the diagram easier to follow. heap stack 1000 num den 1 1004 2 1008 num den 1 num den 5 num den 1 2 100 C num den 1 1010 3 1014 3 1018 num den 1 101 C 6 1020 6 1024 num den 5 1028 6 102 C 1030 num den 1 1034 1 1038 sum c b a 1030 FFEC 1018 FFF 0 100 C 1000 FFF 4 FFF 8 FFFC 6 1 sum c b a

Garbage Collection • One fact that the pointer model makes clear in this diagram

Garbage Collection • One fact that the pointer model makes clear in this diagram is that there are no longer any references to the Rational value 5/6. That value has now become garbage. • From time to time, Java runs through the heap and reclaims any garbage. This process is called garbage collection. heap This object was used to hold a temporary result and is no longer accessible. num den 1 num den 5 num den 1 stack 2 3 6 6 1 sum c b a

Exercise: Stack-Heap Diagrams Suppose that the classes Point and Line are defined as follows:

Exercise: Stack-Heap Diagrams Suppose that the classes Point and Line are defined as follows: public class Point { public Point(int x, int y) { cx = x; cy = y; }. . . other methods appear here. . . } public class Line { public Line(Point p 1, Point p 2) { start = p 1; finish = p 2; }. . . other methods appear here. . . private int cx; private int cy; } private Point start; private Point finish; Draw a heap-stack diagram showing the state of memory just before the following run method returns. public static void main(String[] args) { Point p 1 = new Point(0, 0); Point p 2 = new Point(200, 200); Line line = new Line(p 1, p 2); }

Solution: Stack-Heap Diagrams Address Model Pointer Model stack heap stack 1000 cx cy 0

Solution: Stack-Heap Diagrams Address Model Pointer Model stack heap stack 1000 cx cy 0 1004 0 1008 cx cy 0 cx cy 200 0 100 C cx cy 200 1010 200 1014 1018 start finish 1000 101 C 100 C 1020 line p 2 p 1 1018 FFF 0 100 C 1000 FFF 4 FFF 8 FFFC start finish 200 line p 2 p 1

Primitive Types vs. Objects • At first glance, Java’s rules for passing objects as

Primitive Types vs. Objects • At first glance, Java’s rules for passing objects as arguments seem to differ from the rules Java uses with arguments that are primitive types. • 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. • When you pass an object as an argument, there seems to be some form of sharing going on. Although changing the parameter variable itself has no effect, any changes that you make to the instance variables inside an object—usually by calling setters—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 but not the object itself.

Linking Objects Together • Although most examples of this technique are beyond the scope

Linking Objects Together • Although most examples of this technique are beyond the scope of a first course, references are particularly important in computer science because they make it possible to represent the relationship among objects by linking them together in various ways. • One common example (which you will encounter again in Chapter 13) is called a linked list, in which each object in a sequence contains a reference to the one that follows it: data link null • Java marks the end of linked list using the constant null, which signifies a reference that does not actually point to an actual object. The value null has several other uses, as you will discover in the chapters that follow.

The Beacons of Gondor For answer Gandalf cried aloud to his horse. “On, Shadowfax!

The Beacons of Gondor For answer Gandalf cried aloud to his horse. “On, Shadowfax! We must hasten. Time is short. See! The beacons of Gondor are alight, calling for aid. War is kindled. See, there is the fire on Amon Dîn, and flame on Eilenach; and there they go speeding west: Nardol, Erelas, Min-Rimmon, Calenhad, and the Halifirien on the borders of Rohan. ” —J. R. R. Tolkien, The Return of the King, 1955 In a scene that was brilliantly captured in Peter Jackson’s film adaptation of The Return of the King, Rohan is alerted to the danger to Gondor by a succession of signal fires moving from mountain top to mountain top. This scene is a perfect illustration of the idea of message passing in a linked list. Minas Tirith Amon Dîn Eilenach Nardol Erelas Min-Rimmon Calenhad Halifirien Rohan

Message Passing in Linked Structures To represent this message-passing image, you might use a

Message Passing in Linked Structures To represent this message-passing image, you might use a definition such as the one shown on the right. You can then initialize a chain of Signal. Tower objects, like this: Minas Tirith Min-Rimmon Amon Dîn Calenhad Eilenach Halifirien Nardol Rohan null Erelas Calling signal on the first tower sends a message down the chain. public class Signal. Tower { /* Constructs a new signal tower */ public Signal. Tower(String name, Signal. Tower link) { tower. Name = name; next. Tower = link; } /* * Signals this tower and passes the * message along to the next one. */ public void signal() { light. Current. Tower(); if (next. Tower != null) { next. Tower. signal(); } } /* Marks this tower as lit */ public void light. Current. Tower() {. . . code to draw a fire on this tower. . . } /* Private instance variables */ private String tower. Name; private Signal. Tower next. Tower; }

public static void main(String[] args) { Signal. Tower rohan = new Signal. Tower("Rohan", null);

public static void main(String[] args) { Signal. Tower rohan = new Signal. Tower("Rohan", null); Signal. Tower halifirien = new Signal. Tower("Halifirien", rohan); Signal. Tower calenhad = new Signal. Tower("Calenhad", halifirien); Signal. Tower min. Rimmon = new Signal. Tower("Min-Rimmon", calenhad); Signal. Tower erelas = new Signal. Tower("Erelas", min. Rimmon); Signal. Tower nardol = new Signal. Tower("Nardol", erelas); Signal. Tower eilenach = new Signal. Tower("Eilenach", nardol); Signal. Tower amon. Din = new Signal. Tower("Amin Din", eilenach); Signal. Tower minas. Tirith = new Signal. Tower("Minas Tirith", amon. Din); minas. Tirith. signal(); }