I just had an interview, and I was asked to create a memory leak with Java.
Needless to say, I felt pretty dumb having no clue on how to eve
The following is a pretty pointless example, if you do not understand JDBC. Or at least how JDBC expects a developer to close Connection
, Statement
and ResultSet
instances before discarding them or losing references to them, instead of relying on the implementation of finalize
.
void doWork()
{
try
{
Connection conn = ConnectionFactory.getConnection();
PreparedStatement stmt = conn.preparedStatement("some query"); // executes a valid query
ResultSet rs = stmt.executeQuery();
while(rs.hasNext())
{
... process the result set
}
}
catch(SQLException sqlEx)
{
log(sqlEx);
}
}
The problem with the above is that the Connection
object is not closed, and hence the physical connection will remain open, until the garbage collector comes around and sees that it is unreachable. GC will invoke the finalize
method, but there are JDBC drivers that do not implement the finalize
, at least not in the same way that Connection.close
is implemented. The resulting behavior is that while memory will be reclaimed due to unreachable objects being collected, resources (including memory) associated with the Connection
object might simply not be reclaimed.
In such an event where the Connection
's finalize
method does not clean up everything, one might actually find that the physical connection to the database server will last several garbage collection cycles, until the database server eventually figures out that the connection is not alive (if it does), and should be closed.
Even if the JDBC driver were to implement finalize
, it is possible for exceptions to be thrown during finalization. The resulting behavior is that any memory associated with the now "dormant" object will not be reclaimed, as finalize
is guaranteed to be invoked only once.
The above scenario of encountering exceptions during object finalization is related to another other scenario that could possibly lead to a memory leak - object resurrection. Object resurrection is often done intentionally by creating a strong reference to the object from being finalized, from another object. When object resurrection is misused it will lead to a memory leak in combination with other sources of memory leaks.
There are plenty more examples that you can conjure up - like
List
instance where you are only adding to the list and not deleting from it (although you should be getting rid of elements you no longer need), orSocket
s or File
s, but not closing them when they are no longer needed (similar to the above example involving the Connection
class).