Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用JDBC的内存泄漏应用程序_Java_Mysql_Jdbc_Memory Leaks - Fatal编程技术网

Java 使用JDBC的内存泄漏应用程序

Java 使用JDBC的内存泄漏应用程序,java,mysql,jdbc,memory-leaks,Java,Mysql,Jdbc,Memory Leaks,我使用的是mysql-connector-java-5.1.21,内存分析器怀疑是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: •cl

我使用的是mysql-connector-java-5.1.21,内存分析器怀疑是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. 

如果我使用jconsole执行垃圾收集,堆内存使用率会下降

那么它看起来就不是一个漏洞;也许可以使用-Xmx标志启动JVM,以限制分配给JVM的最大内存量。这可能会更频繁地触发GC


或者在您的循环中执行完整的GC:System.GC()--通常不建议这样做,但如果您的小型应用程序可能会这样做。

Java将创建对象并增加内存,直到接近-Xmx max heap size设置,然后它将运行垃圾收集以释放空间。您应该使用-Xmx设置启动,以控制JVM可以使用多少内存。您还应该知道,默认情况下,Connector/JDBC驱动程序会在内存中缓冲整个结果

虽然我确实看到了一些等待垃圾收集的释放资源,但事实证明大部分都是JDBC连接。重复打开和关闭连接会造成内存泄漏。我切换了代码,因此它只使用一个连接,而jconsole现在没有显示内存泄漏的迹象。用户1443778建议我只需要一个连接,这应该归功于它。PreparedStatements的建议也很好,因为我重写了代码来使用它们


还感谢您提出使用连接池的建议。这是一个很好的建议,但我可能不会担心,直到我们用Tomcat或JBOSS移动到VPS。

如果我用JTROM执行垃圾收集,堆内存使用量就会下降。考虑发布你的代码,这将有助于分析你的发行。这是低于1MB的内存。为什么会出现问题?我们有非常严格的内存限制,因为这是在共享web主机上运行的。堆内存在50分钟内从6mb的峰值增加到7mb以上,并继续增加。我们需要同时运行这个应用程序的两个版本,我相信我们的内存消耗不是很大(低于半个gig)。最终,我们将转移到VPS,但我希望它能够在主持公司不破坏演示过程的情况下运行。使用事先准备好的声明,我认为这不会解决您的问题,但无论如何都是一件好事。此外,我在GUI应用程序中有一些jdbc代码,这些代码在应用程序终止之前一直保持连接,即当用户按下按钮但只打开一个连接时,它会发出准备好的语句jdbc请求。您是否建议我对查询进行限制?当我移动到VPS时,我不确定这是否会成为一个问题,但有可能一次发布多达10000多个的大量事务,并且该流程服务器目前将请求所有10K以及其他来源的任何新事务。或者有连接器/JDBC的替代品吗?是的,我肯定会限制您的查询。如果批量较大,可能需要几轮才能完成,但这比应用程序内存不足要好得多。
    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");
        }
    }