Java 101: Trash talk, Part 1

Java recycles its memory through garbage collection

1 2 3 4 5 Page 3
Page 3 of 5

Run Java's garbage collector

Regardless of the garbage collection algorithm(s) that a JVM uses, you can always request that the JVM perform garbage collection by executing System.gc ();. According to the SDK documentation, System's gc() method:

... suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.

And why might you want to explicitly ask the JVM to run the garbage collector? Suppose you need to execute a long-running series of calculations that require a large amount of heap memory. Having the garbage collector clear out unreachable objects before those calculations begin yields more free heap memory for those calculations. The result: they complete much more quickly.

System's gc() method calls Runtime.getRuntime ().gc ();.

Finalize objects

Before a garbage collector can collect a Java object, it must finalize that object, meaning it must allow the object to release any acquired finite resources. Finite resources are those resources in short supply, such as file and socket handles, graphics contexts, or a sound card. Think of finalizing objects as giving an object a second chance to release finite resources. And when does the object receive its first chance to release those resources? For an answer to that question, consider the following three finite resource acquisition and release scenarios:

  1. You can acquire and release a resource in the same method. Although that guarantees that resource's release, a time cost results when acquiring the resource. Because you must acquire the resource each time you call the method, that time cost can turn into a significant performance penalty.
  2. You can acquire a resource in one method and free that resource in another. Although this solves the performance problem (because you do not need to repeatedly acquire the resource), you might forget to call the method that acquires the resource but call the method that releases the resource anyway. That forgetfulness can lead to subtle bugs in your code, and those bugs might be hard to find.
  3. You can acquire the resource in a constructor and release that resource in another method. Although this guarantees that the resource is present before you begin to work with the object, you can acquire the resource only once during the object's life. Despite that limitation, Java's standard class library is replete with examples that acquire finite resources in constructors and provide release mechanisms via other methods. For example, the FileInputStream class acquires a file handle in either of its constructors and releases that file handle through its close() method.

The third approach to resource acquisition and release seems ideal. However, you might forget to call a release method or an exception might prevent a call to a release method from occurring. (I explore exceptions in an upcoming article.) Either way, your code fails to release a previously acquired resource, and that failure leads to a resource leak. For example, you probably will not be able to reopen a file that is already open. Although you should make every effort to ensure that your code always calls appropriate release methods, in the event that you fail to explicitly release those resources, Java provides a fallback mechanism (the object's second chance), known as finalization, to help ensure the release of finite resources.

Finalization involves the garbage collector running an object's finalize() method prior to that object's collection. Within the finalize() method, the object can release all acquired finite resources. Recall from "Object-Oriented Language Basics, Part 5" that finalize() is one of Object's 11 methods and features the following signature:

protected void finalize() throws Throwable

The finalize() method does not return anything; why should it? After all, the object should cease to exist after finalize() returns. As a result, finalize()'s signature specifies the void keyword to mark its return type. Notice the throws Throwable clause that attaches to the signature. That clause signifies that code within finalize() can throw any kind of exception. However, if that code should throw an exception, the garbage collector will ignore it.

1 2 3 4 5 Page 3
Page 3 of 5