我正在使用mysql-connector-java-5.1.21,我遇到了内存泄漏,memory Analyzer怀疑是java.lang.class和最大的实例之一出现了mysql。jdbc。我已经仔细检查了代码,并确保所有连接、结果和语句都已正确关闭。我仍然会收到泄漏。
1,529 instances of "java.lang.Class", loaded by "<system class loader>" occupy 711,632 (41.68%) bytes.
Biggest instances:
•class com.mysql.jdbc.NonRegisteringDriver @ 0x381323f8 - 97,400 (5.70%) bytes.
•class java.io.ObjectStreamClass$Caches @ 0x3d070568 - 91,872 (5.38%) bytes.
•class java.lang.System @ 0x3d03da20 - 67,224 (3.94%) bytes.
•class com.mysql.jdbc.SingleByteCharsetConverter @ 0x382a7438 - 66,032 (3.87%) bytes.
•class java.lang.ref.Finalizer @ 0x3d03e260 - 65,888 (3.86%) bytes.
•class com.sun.org.apache.xerces.internal.util.XMLChar @ 0x380bc528 - 65,592 (3.84%) bytes.
•class com.mysql.jdbc.ConnectionPropertiesImpl @ 0x381ab5f8 - 32,456 (1.90%) bytes.
该代码在一个有延迟的循环中运行。目前,代码在每个间隔打开一个连接。我应该只打开一个连接并将其传递给我的方法吗?不管怎样,我都不确定为什么会导致泄漏。感谢您的帮助。
下面是一些代码,它应该让您对我如何使用jdbc和mysql有一个很好的了解。
try {
url+=database+"?zeroDateTimeBehavior=convertToNull";
// LatestTime in SQL table defaults 0000-00-00 00:00:00 which java can't handle. zeroDateTimeBehaviour=convertToNull cause JDBC to null for a zero date.
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection(url,user,password);
System.out.println(CurrentTime()+": "+"Connected to "+database);
}
catch (Exception e)
{
System.err.println(CurrentTime()+": "+e.getMessage());
System.err.println(CurrentTime()+": "+"Unable to Connect");
}
finally
{
if (conn!=null)
{
try {
// Create Statements for SQL queries
Statement query= conn.createStatement();
// Get all records from phonelog which have yet to be processed
query.executeQuery("SELECT * from phonelog where Recordnum>"+Recordnum);
ResultSet rs = query.getResultSet();
// Process each row from query result
while (rs.next()) {
}
JDBCHelper.close(rs);
String plupdate="update Counters set value='"+Recordnum+"' where name='plposition'";
submit.executeUpdate(plupdate);
JDBCHelper.close(query);
}
catch (SQLException SQLe) {
System.err.println(CurrentTime()+": "+SQLe.getMessage());
}
JDBCHelper.close(conn);
System.out.println (CurrentTime()+": "+"Disconnected");
}
}
Java将创建对象并占用内存,直到接近-Xmx最大堆大小设置,然后运行垃圾收集以释放空间。您应该使用-Xmx设置启动,以控制JVM可以使用的内存量。您还应该注意,Connector/JJDBC驱动程序默认情况下会将整个结果缓冲在内存中。
如果我使用jconsole执行垃圾收集,则堆内存使用率会回落到
那么,它似乎并没有泄漏;也许您可以使用-Xmx标志来启动JVM,以限制分配给JVM的最大内存量。这可能会更频繁地触发GC。
或者在循环中执行一个完整的GC:System.GC()——通常根本不建议这样做,但在您的小型应用程序可能会成功的情况下。
虽然我看到的确实是等待垃圾收集的释放资源,但事实证明,这主要是JDBC连接。重复打开和关闭连接会造成内存泄漏。我切换了代码,使其只使用一个连接,并且jconsole现在没有显示内存泄漏的迹象。应该感谢user1443778建议我只需要一个连接。PreparedStatments建议也很好,因为我重写了代码以使用它们。
也感谢您提出的使用ConnectionPool的建议。这是一个很好的建议,但在我们转向使用Tomcat或JBOSS的VPS之前,我可能不会考虑这个问题。