Java内存泄漏经典原因分析
- Java内存泄漏经典原因分析:
- 对象定义在错误的范围(Wrong scope);
- 异常(Exception)处理不当;
- 集合数据管理不当。
-
对象定义在错误的范围(Wrong scope)
- 如果Foo实例对象的生命较长,会导致临时性内存泄漏。(这里names变量其实只有临时作用)
class Foo{ private String[] names; public void odIt(int length){ if(names == null || names.length < length){ names = new String[length]; } populate(names); print(names); } }
- JVM喜欢生命周期短的对象,这样做已经足够高效:
class Foo{ public void odIt(int length){ String[] names = new String[length]; populate(names); print(names); } }
-
异常处理不当:
-
错误的做法:
Connection conn = DriverManager.getConnection(url,name,passward); try{ String sql = "do a query sql"; PreparedStatement stmt = conn.prepareStatement(sql); ResultSet rs = stmt.executeQuery(); while(rs.next()){ doSomeStuff(); } rs.close(); conn.close(); }catch(Exception e){ //如果doSomeStuff()抛出异常 //rs.close 和 conn.close 不会被调用, //会导致内存泄漏和db连接泄漏 }
-
正确的做法:
PreparedStatement stmt = null; ResultSet rs = null; try{ String sql = "do a query sql"; stmt = conn.prepareStatement(sql); rs = stmt.executeQuery(); while(rs.next()){ doSomeStuff(); } }catch(Exception e){ //handle exception }finally{ //永远用finally去关闭资源,避免资源泄漏 if(rs != null){ rs.close(); } if(stmt != null){ stet.close(); } conn.close(); }
-
-
集合数据管理不当:
- 当时用Array-based的数据结构(ArrayList,HashMap等)时,尽量减少resize
- 比如:new ArrayList时,尽量估算size,在创建的是把size确定;
- 减少resize可以避免没有必要的array copying , gc碎片等问题;
- 如果一个List只需要顺序访问,不需要随机访问(Random Access),用LinkedList代替ArrayList
- LinkedList本质是链表,不需要resize,但只适用于顺序访问。
- 当时用Array-based的数据结构(ArrayList,HashMap等)时,尽量减少resize