How can I create a memory leak in Java?

后端 未结 30 1702
没有蜡笔的小新
没有蜡笔的小新 2020-11-21 22:26

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

30条回答
  •  囚心锁ツ
    2020-11-21 22:31

    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

    • Managing a 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), or
    • Opening Sockets or Files, but not closing them when they are no longer needed (similar to the above example involving the Connection class).
    • Not unloading Singletons when bringing down a Java EE application. Apparently, the Classloader that loaded the singleton class will retain a reference to the class, and hence the singleton instance will never be collected. When a new instance of the application is deployed, a new class loader is usually created, and the former class loader will continue to exist due to the singleton.

提交回复
热议问题