United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4363937 : ObjectOutputStream is creating a memory leak

Details
Type:
Bug
Submit Date:
2000-08-18
Status:
Closed
Updated Date:
2001-01-10
Project Name:
JDK
Resolved Date:
2001-01-10
Component:
core-libs
OS:
linux,windows_2000
Sub-Component:
java.io:serialization
CPU:
x86
Priority:
P4
Resolution:
Not an Issue
Affected Versions:
1.3.0,1.3.1
Fixed Versions:

Related Reports
Duplicate:
Relates:

Sub Tasks

Description

Name: skT45625			Date: 08/18/2000


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

When using a loop to serialize objects to a file, the ObjectOutputStream object
never seems to release the references to objects that have already been written
to the file.  Since the garbage collector can't clean up these objects, it's
relatively simple to generate an OutOfMemoryError.

Here is some sample code:

public class MyObject() {
    static public void main(String[] args) {
        try {
            File file = File.createTempFile("test", null);
            FileOutputStream testFile = new FileOutputStream
(file.getAbsolutePath(), true);
            ObjectOutputStream testOut = new ObjectOutputStream(testFile);

            // Write a bunch of double arrays to the file
            for (int i = 0; i < 100; i++) {
                testOut.writeObject(new double[1000000]);
                testOut.flush();
            }

            testOut.close();
            testFile.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Before the program finishes, an OutOfMemoryError is generated (using the
default memory allocation for the virtual machine).  Shouldn't each double
array be marked for garbage collection once it has been written to the stream?
If so, is this an io error or a garbage collection error?
(Review ID: 108636) 
======================================================================

Name: krC82822			Date: 10/13/2000


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0)
Java HotSpot(TM) Client VM (build 1.3.0, mixed mode)


import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.File;
import java.io.FileOutputStream;

public class MemoryTest
{
	public static void main(String[] args)
	{
		try
		{
			File file = new File("/dev/null");
			long quantity = Long.parseLong(args[0]);

			ObjectOutputStream out
			          = new ObjectOutputStream(new FileOutputStream(file));

			for(long i = 0; i < quantity; i++)
			{
				out.writeObject(new Long(i));

				// eval1127:  even a flush() here after every 200 objects did not help
				
				if ((i % 50000) == 0)
				{
					System.out.println(""+i);
				}
			}
		}
		catch(Exception e)
		{
			System.out.println(e.toString());
		}
	}
}

The above code produces an OutOfMemoryError when the iteration count is high
enough.

Suggest you run as:

java -Xmx10M -Xms10M  MemoryTest 10000000

This produces the following output:

0
50000
100000
150000
200000
250000
Exception in thread "main" java.lang.OutOfMemoryError
        <<no stack trace available>>

This has been tested on Linux, Solaris and Windows NT.  All were using JDK1.3.
All produced the same output.

I'm assuming the error is something to do with Serialization as the error does
not seem to occur when the writeObject line is removed.
(Review ID: 110753)
======================================================================

                                    

Comments
EVALUATION

This is not a bug; it is simply how serialization works.  As noted in the
comments for this bug, ObjectOutputStream must maintain a table of written
objects in order to determine when to write back-references to objects already
serialized in the stream.

The comments also note that ObjectOutputStream's handle table could use weak
references instead to avoid unnecessarily pinning objects.  While attractive,
this would slow performance; moreover, the serialization protocol does not
include any means for a sender to indicate to a receiver that a given object
has been reclaimed on the sending side and hence should be released in the
receiver's handle table as well.  Thus, a memory leak would still exist on the
receiving side, and using weak references on the sending side would encourage
programming practices (i.e., not calling ObjectOutputStream.reset()) which
would exacerbate the receiver's memory leak.

The proper way to prevent memory leaks when serializing large numbers of
objects is to periodically reset() the ObjectOutputStream.  In addition to
clearing the sender's handle table, this sends a reset code to the receiver,
indicating that the receiving ObjectInputStream should also clear its handle
table, in the process unpinning objects on both sides of the communication.

michael.warres@east 2001-01-10
                                     
2001-01-10
WORK AROUND



Name: skT45625			Date: 08/18/2000


None.
======================================================================


Call ObjectOutputStream.reset().  See evaluation for details.

michael.warres@east 2001-01-10
                                     
2001-01-10



Hardware and Software, Engineered to Work Together