UPI Study › Courses › Data Structures and Algorithms › Free lessons › Lesson 17.7 Free with a free account
How Java Allocates, Tracks, and Reclaims Memory
Data Structures and Algorithms · Chapter 17: Graphs and MemorySection 17.7 · lesson 84 of 879 min · free with a free account
Free preview
Create a free account to keep watching
It takes a minute and costs nothing. Your free account unlocks all of Chapter 1 and 3 more lessons of Data Structures and Algorithms.
Lesson complete
Earn the 3 college credits for Data Structures and Algorithms
Enrolling adds a quiz after each lesson, the graded work and the official transcript. Recommended for credit by NCCRS.
Next lesson: Why Frequently Used Data Lives in Faster, Smaller Memory →← Solving Real Problems by Modeling Them as NetworksNext lesson: Why Frequently Used Data Lives in Faster, Smaller Memory →
In this lesson
How the stack, heap, references, and garbage collector manage memory.
- Distinguish what Java stores on the stack from what it stores on the heap
- Predict the effect of copying and passing references to objects and arrays
- Explain reachability-based garbage collection and generational collection
- Recognize and fix memory leaks in data structures
Free study notes
Get this lesson's notes by email
The key points and 4 practice questions with answers, in your inbox. One email, free.
One email. Unsubscribe in one click.
Transcript
Everything said in the video, section by section (1,320 words). Read along, or search it.
Opening Question
A Desk, a Warehouse, and a Janitor
Think of a desk and a warehouse. The desk holds the papers for the job in hand, and it's cleared the moment the job ends. The warehouse holds everything that must outlast one job. An item stays on its shelf while somebody holds a ticket that leads to it. When the last ticket is gone, a janitor clears the shelf. Java works the same way: the stack is the desk, the heap is the warehouse, references are the tickets, and the garbage collector is the janitor. So how can a program whose data structure works perfectly still run out of memory?
Stack and Heap
Frames on the Stack, Objects on the Heap
Every running thread owns a stack, a pile of frames. A method call puts a new frame on top, holding that call's parameters and local variables. The frame vanishes the instant the method returns, with no cleanup work at all. A primitive, like an int, sits right inside the frame. Any other local holds only a reference. The object itself lives on the heap, one large pool shared by every thread. Everything made with new, every array included, lives there, until no reference can reach it.
Stack Overflow
Recursion With No Stopping Condition
A stack has a fixed size per thread. This method calls itself with no stopping condition, so each call adds one more frame. Eventually there's no room for another, and Java throws a StackOverflowError, which can be caught. Run it. On one test machine it took roughly twenty thousand calls or more, and the exact count changed between runs. So recursion tens of thousands of levels deep, down a long linked list or a badly unbalanced tree, can overflow the stack while the heap is nearly empty.
Allocation
Object Headers and Boxed Number Costs
What does new do? It finds room in the part of the heap for new objects, sets every field to its default, runs the constructor, and hands back a reference. Finding room is fast. Free memory there is handed out in order, like tearing the next sheet off a pad. Every object starts with a header, and its size rounds up to a multiple of eight bytes. Measured on 64-bit Java 21, a Point with two ints takes 24 bytes. An int array of ten takes 56. An Integer array of ten is also 56, but it holds only references. Each boxed number is another 16-byte object. So a thousand boxed numbers above 127 take about 20,016 bytes, against 4,016 for an int array: about five times as much.
References
Copying a Reference, Not the Object
A variable of an object type holds a reference. So copying the variable copies the address, never the object. Run it. The primitive y was a true copy, so changing it left x alone. But after b equals a, there's one array with two names. Setting b of zero to 99 shows up through a. Once b is pointed at a new array, a keeps the old one. A called method can change the shared array, as poke does. But it can't re-aim the caller's variable, as rebind tries to, because it only received a copy of the reference.
Quick Check
Three Variables and Two Arrays
Quick check. Three variables, two arrays. Follow which name points where, and which array each change lands in. What does the last line print? Pause and predict. One, seven. b briefly named a's array, but then it was pointed at a new one, so b of zero equals nine changed only the new array. c, though, is another name for a's array. So c of one equals seven lands in a.
Garbage Collection
Reachability From the Roots
Java has no operation to free an object. The garbage collector uses one rule: an object may be reclaimed once the program can no longer reach it. The starting points are the roots: the locals and parameters in active frames, and the static fields. An object is reachable if some chain of references leads to it from a root. The collector marks everything it can reach, then reclaims whatever wasn't marked. Because the rule is about reachability, not counting references, a cycle doesn't protect anything. This program links a and b to each other, and watches them through weak references, which don't keep an object alive. Run it. While the locals hold them, both survive a collection. Once both locals are null, the pair is reclaimed, even though they still point at each other. Now, a caution. Setting a variable to null frees nothing by itself: it removes one ticket. And System.gc is only a request. It's used here so the test doesn't have to wait.
Quick Check
An Unreachable Cycle Is Garbage
Quick check. Here, a is a local that keeps living. a points to b, b points to c, and c points back to b. Then the program cuts the link from a to b, and asks for a collection. What do the two lines print? Pause and predict. Both false. The only root here is the local a, and after the cut, no chain of references leads from it to b or c. b and c still point at each other, but a cycle with no path from a root is just garbage.
Generations
Most Objects Die Young
Studies of real programs keep finding the same thing: most objects die young. So collectors split the heap into generations. New objects go into Eden. When Eden fills, a young collection copies the few survivors out and empties the rest at once. Its cost follows the survivors, not the garbage. Objects that keep surviving are promoted to the old generation. That's collected rarely, in a full collection, which examines the whole heap and pauses much longer. In one test, making 20 million short-lived arrays took 89 young collections, no full one, and 13 milliseconds of pause in all. Keeping just one array in 40 forced a full collection, and the total pause grew to 216 milliseconds.
Memory Leak
A Stale Slot in an Array Stack
The collector frees everything unreachable, so Java can't forget to free memory. It can still leak. A leak is an object you'll never use again that's still reachable. Leaks hide in data structures, because a structure is exactly a set of references keeping things alive. The first pattern is a stale slot. An array-based stack tracks its top with a counter. A pop that only lowers the counter leaves the old reference in the slot above the top. The stack treats that slot as empty, but the collector sees an ordinary reference. Run it: ten one-megabyte arrays, pushed, popped, then a collection. The leaky stack is empty by its own count, yet all ten arrays survive. The safe pop clears the slot, and all ten are released.
Memory Leak
Entries That Are Never Removed
Java's own ArrayList clears the slot when it removes an element. The trap appears when you write your own array-backed structure. The second pattern is entries never removed: a static list, a registry of listeners, a history of requests. If a program only adds, its heap use only grows. In one test, a history that kept every one-kilobyte buffer grew about a megabyte per thousand buffers. A window of the latest thousand stayed flat at two. With the heap capped at 16 megabytes, the history ran out of memory after 14,114 entries. Anything that remembers needs a rule for forgetting.
Memory Leak
Capacity Kept After Clearing
The third pattern is capacity kept after the elements are gone. A dynamic array grows, but it doesn't shrink when you remove things. In one test, an ArrayList of 3 million boxed numbers used 63 megabytes. Clear dropped that to 17: the numbers were released, but the big backing array stayed. trimToSize gave the rest back, down to one megabyte. To spot a leak, watch the heap after each collection: a steady saw-tooth is healthy, a creeping level is not.
Key Takeaways
Java Memory in Brief
To sum up. Frames live on the stack and vanish on return. Objects live on the heap. Copying a reference never copies the object. An object is reclaimed once no chain from a root reaches it, cycles included. Young collections are cheap, full ones are not. And a leak is reachable memory you'll never use: clear stale slots, limit what you remember, and trim capacity.
About Data Structures and Algorithms at UPI Study
Data Structures and Algorithms (Computer Science 251) is a self-paced online course of 87 video lessons in 17 chapters, from Java and object-oriented design to arrays, linked lists, recursion, stacks and queues, trees, heaps, hash tables, sorting and graphs. It carries a NCCRS credit recommendation for 3 semester credits.
Every lesson transcript is free on pages like this one, and the videos are free with a free UPI Study account. Enrolling adds a practice quiz after each lesson, the graded work and final exam that earn the credit, lifetime access, and an official transcript on completion. UPI Study has helped over 130,000 students with college credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
Enroll now → Course details Download the syllabus All Computer Science courses Every course with PRO →
Compare: Discrete Math vs Data Structures and Algorithms · Intro to Java vs Data Structures and Algorithms
Why take it here
Why students take Data Structures and Algorithms with UPI Study
Where the credit goes
Universities that work with NCCRS
Data Structures and Algorithms carries a NCCRS credit recommendation. These universities work with NCCRS; some are UPI Study's signed partners. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
Thomas Edison State UniversitySigned partner
University of the PeopleSigned partner
Charter Oak State CollegeSigned partner
Strayer UniversitySigned partner
Columbia Southern UniversitySigned partner
Indiana TechSigned partner
Penn StateWorks with NCCRS
Southern New Hampshire UniversityWorks with NCCRS
SUNYWorks with NCCRS
+many more cooperating universitiesFind my college →Find my college → Not listed? Ask Athena in the corner of this page, or book a 15-minute call.
FAQ
Questions students ask us
About How Java Allocates, Tracks, and Reclaims Memory
What is the difference between the stack and the heap in Java?
Is Java pass by reference or pass by value?
How does Java garbage collection decide what to free?
Can Java have memory leaks?
About the Data Structures and Algorithms course
How many college credits is Data Structures and Algorithms?
How much does Data Structures and Algorithms cost and what is included?
Which universities accept UPI Study credits?
How long does Data Structures and Algorithms take?
How are the exams done?
How do my credits reach my college?
Ready for the full course? Earn 3 credits in Data Structures and Algorithms.
87 video lessons, a quiz after each one, and the graded work that earns the credit. Recommended for credit by NCCRS.
3 credits · NCCRSEnroll →