Garbage Collector
Theory
As you already know, when a JVM language program creates a new object, a part of the heap memory is being used. What happens when there is no available heap memory left? How does the JVM know what parts of memory may be reused for something else? In this topic, we will tackle these questions and learn about garbage collection — a way to perform automatic memory management.
§1. Memory management strategies
The heap memory, even if big enough for most programming tasks, is still limited, as it takes part of the physical memory (RAM) on the computer. So a program taking too much memory will eventually lead to crashes. Most programs have objects that at some point of the execution won't be used anymore, which means the memory may be freed and reused later.
Some programming languages (for example, C or C++) require programmers to allocate and free memory manually. Although this provides more control over the resources, manual memory management may be a challenging task, especially for beginners, resulting in errors and memory leaks.
The JVM utilizes automated memory management, which allows developers not to worry about memory while writing code and prevents possible programming mistakes. Memory is allocated in the JVM heap every time a program creates a new object and is freed using the garbage collection process.
§2. What is Garbage Collection?
The Garbage Collector (or GC) is a part of the JVM that frees up the memory in runtime for further use. There are much different garbage collection algorithms and implementations, but their work may be simplified into two common steps. The first step is to determine which parts of memory the program no longer uses (i.e., "garbage"), and the second step is to free these parts of memory. Additionally, a compacting operation may be performed after the deletion step — all currently used objects are moved next to each other to free a big contiguous memory region and avoid fragmentation.
In order to identify garbage, the JVM goes through all the objects and checks whether they are still reachable in the program. All objects that can't be reached from the program or from other reachable objects are considered "garbage", and the corresponding memory is freed up.
Some algorithms take into account additional information about objects, for example, the time since the object was created. Such algorithms are called generational garbage collection algorithms. It has been noticed that most objects in programs are used only for a short time after creation. Thus, the garbage collector doesn't need to examine every object in the heap on every run and focuses mainly on recently created objects (the "younger generation"), which reduces the garbage collection time.
§3. Running GC
Garbage collection is performed automatically while a program is running. The JVM handles all the dirty work itself, including the decision when to run the GC. It may happen, for example, in fixed time intervals or when there is no free heap memory left.
In most cases, developers don't need to think about how the garbage collector works and how to customize it. However, in modern high-load applications, this knowledge may be useful.
In your programs, you may use the following ways to request the GC to perform the job:
- calling System.gc();
- calling Runtime.getRuntime().gc().
Programmers aren't supposed to run the garbage collector manually, and these calls don't even guarantee the GC invocation. We strongly recommend using them only in a test environment.
§4. Example
Let's say that we have a code to check the used memory size (you can do it using Runtime.getRuntime().totalMemory() and Runtime.getRuntime().freeMemory()), and we put it in a program that works the following way:
- Print the used memory information before performing any operations.
- Create a bunch of new objects in a cycle for further use.
- Print the used memory information after the objects' creation.
- Perform the necessary operations (without creating new objects) so that the objects are no longer used in the code.
The value from step 3 will be greater than the value from step 1, since each new object takes some part of the available memory. After step 4, the objects become unreachable from the code and the memory may be freed up by calling System.gc() or Runtime.getRuntime().gc(). Printing the used memory information after the garbage collector invocation will show a value less than the value from step 3 if garbage collection was really performed.
§5. Conclusion
- The JVM performs automated memory management, protecting programmers from possible memory leaks and errors.
- The Garbage Collector (GC) is a part of the JVM that identifies the unused "garbage" objects and cleans the corresponding memory regions to reuse them later.
- The GC may be invoked manually in the code, but it is not guaranteed that the garbage collection will be performed, as the decision is still up to the JVM.
You can also view Lesson on hyperskill.org.
Practical tasks and answers
Tasks and answer options are given. The correct option is highlighted in blue color.
№1. Invoking GC using Runtime
Question: Select the statement that describes what the following line of code does to the garbage collector:
Runtime.getRuntime().gc()Select one option from the list:
- It does not affect the behavior of the GC
- Forces the GC to be executed immediately
- Requests the GC to be executed, but it doesn't necessarily happen ✔
- Forces the GC to be executed exactly one second later
Explanation. The statement "Runtime.getRuntime().gc()" requests the GC to be executed, but it doesn't necessarily happen.
№2. Why do we need it
Question: What's the purpose of the garbage collection process?
Select one option from the list:
- To reduce the number of required variables
- To create new objects
- To clean the memory from unused objects ✔
- To terminate a program
Explanation. The purpose of the garbage collection process is to clean the memory from unused objects.
№3. Getting the used memory using Runtime
Question: How can you get the currently used memory size in bytes with the following calls?
- Runtime.getRuntime().totalMemory(), which returns the amount of memory (in bytes) available for created and future objects.
- Runtime.getRuntime().freeMemory(), which returns the amount of memory (in bytes) available for future objects.
Select one option from the list:
- Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() ✔
- (Runtime.getRuntime().totalMemory() + Runtime.getRuntime().freeMemory()) / 1024
- Runtime.getRuntime().freeMemory() - Runtime.getRuntime().totalMemory()
- Runtime.getRuntime().totalMemory() / 1024
Explanation. The currently used memory size in bytes can be obtained by subtracting the amount of free memory from the total memory available, like this: Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory().
№4. Save resources
Question: What does the garbage collector save?
Select one option from the list:
- CPU
- Disk memory
- Network traffic
- RAM ✔
Explanation. The garbage collector saves RAM (Random Access Memory) by freeing up memory occupied by unused objects.
№5. What can be collected
Question: Consider code that does the following:
- Creates a string array bookNames and an integer array bookPages, both of length 1000.
- Creates 1000 objects of the class Book with a string member bookInfo composed using bookNames and bookPages values of the same index.
- Prints bookInfo of all created book objects.
What can be cleaned up during the garbage collection process after each of the steps above? Assume that the program starts right before step 1 and terminates right after step 3 without performing any additional operations.
Match the items from left and right columns:
- After step 1 - None of the mentioned objects
- After step 2 - bookNames and bookPages arrays
- After step 3 - Objects of the Book class
Explanation. 1. Creation time no destruction and expulsion; 2. GC time for small parts; 3. GC time for whole objects.
№6. GC behavior
Question: Select one correct statement about the garbage collector.
Select one option from the list:
- Programmers should manually call the GC before stopping the program to avoid memory leaks
- The GC cleans memory only when there is no free memory left
- The GC automatically cleans memory only before program termination
- The GC works automatically while a program is running ✔
Explanation. The GC works automatically while a program is running.
№7. Invoking GC
Question: How can you request the garbage collector to perform cleaning?
Select one or more options from the list:
- System.out.println("need gc")
- GC.clean()
- Runtime.getRuntime().gc() ✔
- System.gc() ✔
Explanation. You can request the garbage collector to perform cleaning using Runtime.getRuntime().gc() or System.gc().
What is Garbage Collection?
Garbage Collection is a process in which the Java Virtual Machine (JVM) automatically frees up memory that is no longer being used by objects in a program. When a Java program creates objects, the JVM allocates memory to store those objects. However, when an object is no longer needed, it becomes eligible for garbage collection. The garbage collector identifies and removes these unused objects, freeing up memory for other objects to use. This process helps to prevent memory leaks and improves the performance of the program by reducing the amount of memory that needs to be managed by the program itself. In Java, developers do not need to manually free up memory as the JVM takes care of it through automatic garbage collection.