Serialization can prevent garbage collection and thus consequently induce memory leaks. Every time an object is written out to a stream, a reference (or handle) to the object is retained by a table maintained by ObjectOutputStream
. If the same object (regardless of its contents) is written out to the same stream again, it is replaced with a reference to the originally cached object. The garbage collector cannot reclaim the memory associated with new objects as it cannot deal with live references.
...
This noncompliant code example writes an array object arr
to the underlying a stream. The object is created afresh within the loop and filled uniformly with the value of the loop counter. Unfortunately, This may result in an OutOfMemoryError
surfaces as because the stream is kept open while new objects are being written to it.
Code Block | ||
---|---|---|
| ||
class MemoryLeak {
public static void main(String[] args) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(
new BufferedOutputStream(new FileOutputStream("ser.dat")));
for (int i = 0; i < 1024; i++) {
byte[] arr = new byte[100 * 1024];
Arrays.fill(arr, (byte) i);
out.writeObject(arr);
}
out.close();
}
}
|
Compliant Solution
Ideally, the stream should be closed as soon as the work is accomplished. This compliant solution adopts an alternative approach by resetting the stream after every write so that the internal cache no longer maintains live references, allowing the garbage collector to resume.
...