Introduction to Garbage Collection
Memory Managment
Memory management is a central aspect in software development. Applications regularly create new objects, and objects regularly go out of scope and are no longer capable of being referenced. Let's take a look at what this means with a code snippet:
class HelloWorld{
String message;
printHelloMessage(String name){
message = "Hello " + name;//New String instance "message" created
print(message);
} //reference to message is lost once scope leaves method
}
In the above example, message
is assigned a reference value, a "hello" message, at the start of printHelloMessage()
. Once scope leaves printHelloMessage()
, the reference value assigned to message
is no longer reachable, but still exists in memory. Everytime printHelloMessage()
is executed, a new reference value is assigned to message
and allocated memory. If a process does not exist to remove these references from memory, eventually the application might run out of memory, as all available memory is being consumed by dead references.
In languages like C and C++, removing a reference would be handled manually (e.x. by calling free
or delete
). This removes the reference from memory allowing the memory to be reclaimed by the system for reuse.
Manual memory management does have some advantages. Developers have precise control over when an object is removed. Manual memory management might also be more efficient as no background process is running, consuming system resources monitoring memory usage. Though this advantage is less significant as modern automated memory systems have have improved in performance.
However manual memory management comes with some significant downsides. With manual memory management, developers have to be conciously aware of how an application is using memory. This can be a time consuming and difficult, requiring developers to add control code for the safe allocation and deallocations of objects from memory. This code could also be distracting to other developers looking at the code, or the same developer later returning some code they have written, as it obscures the business meaningful work the code is attempting to accomplish. A developer might also fail to properly handle error conditions, which might result in objects not being deleted, leading to a memory leak.
The considerable effort involved in manual memory management and computers rapidly becoming more powerful saw a transition to automated memory management. Today most modern programming languages, including Java, handle memory management automatically with a garbage collector.
Memory Management in Java
Within Java, memory management is handled by a garbage collector, which is part of the Java Virtual Machine (JVM). Within the JVM a garbage collector is a background process that monitors objects in memory. Periodically the garbage collector will run a garbage collection which checks if objects in memory are still reachable, remove objects that are not reachable, and reorganize the objects that are still alive to make more efficent usage of memory and improve future garbage collections.
Garbage collectors considerably reduces the amount of time and effort developers must spend managing memory. Often developers do not need to consiciously consider memory management. Garbage collection also helps to vastly reduce, though not eliminate, issues like memory leaks.
We will take a deeper look at how garbage collectors behave in Java in the next section.
Last update: September 14, 2021