Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/66.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 mysql java.lang.OutOfMemoryError:java堆空间_Java_Mysql_Eclipse_Multithreading - Fatal编程技术网

java mysql java.lang.OutOfMemoryError:java堆空间

java mysql java.lang.OutOfMemoryError:java堆空间,java,mysql,eclipse,multithreading,Java,Mysql,Eclipse,Multithreading,我开发了一个网络刮板。Web scraper使用6个线程,每个线程打开一个网页,获取一篇文章的文本,然后(使用驱动程序)将文本的每个单词写入mysql数据库 在程序执行期间,我得到一个java mysql java.lang.OutOfMemoryError:java堆空间。我在Eclipse上安装了Memory Analyzer,发现问题是由mysql驱动程序连接引起的:当我运行这个程序时,5分钟后驱动程序占用的ram是6MB,5分钟后是200MB,5分钟后是500Mb,然后我得到java错误

我开发了一个网络刮板。Web scraper使用6个线程,每个线程打开一个网页,获取一篇文章的文本,然后(使用驱动程序)将文本的每个单词写入mysql数据库

在程序执行期间,我得到一个java mysql java.lang.OutOfMemoryError:java堆空间。我在Eclipse上安装了Memory Analyzer,发现问题是由mysql驱动程序连接引起的:当我运行这个程序时,5分钟后驱动程序占用的ram是6MB,5分钟后是200MB,5分钟后是500Mb,然后我得到java错误堆空间

我不明白为什么会这样

下面是我用于模型的代码(用于访问mysql数据库)

每个线程只需调用insertCat方法,并在数据库中插入一个带有类别的单词

Eclipse的内存分析器插件说:


该代码从不关闭与数据库的连接

尝试在
insertCat
方法中创建/关闭连接。应尽快获得并释放连接。连接只应在执行持久性操作所需的时间内打开

public class model {

    public synchronized void insertCat(String parola, String categoria){
        Connection connect = null;
        try{
            Class.forName("com.mysql.jdbc.Driver");
            connect = DriverManager.getConnection("jdbc:mysql://localhost/system?user=keyword_tool&password=l0gripp0");
            PreparedStatement statement = connect.prepareStatement("insert into sostantivi (nome, categoria) values (?, ?)");
            statement.setString(1, parola);
            statement.setString(2, categoria);

            statement.executeUpdate();
            statement.close();

        } catch (Exception e){
            //System.out.println(e);
        }finally{
           if(connect != null){
               try {
                  connect.close();
               } catch (Exception e) {
                  System.out.println(e);
               }
           }
        }

    }

}

如果您创建新模型而不销毁它,将创建一个新连接,地图中有2000000个模型,因此您将有2000000个连接


您应该将所有连接代码提取到连接管理器池中,然后自己管理连接

根据您的评论,您只创建了一个“模型”(这是一个坏的类名),并在6个线程中使用它

这并不是一个特别好的设计——它要么由于在单个DB连接上进行同步而限制了性能(当您可以在每个线程上使用一个连接时),要么会遇到潜在的并发问题/错误

我在堆转储中只看到一个
com.mysql.jdbc.JDBC4Connection

这可能是由于误导性的显示,或者(哪种理论符合您声称的“单一模型”方法)它充满了预先准备好的声明或其他东西

理论上,这些应该被缓存和重用——实际上,您遇到了一个问题。有三个步骤可以尝试:

  • 更新MySQL驱动程序版本
  • 每1000次左右关闭并重新打开连接
  • 为每个线程提供自己的连接,或者使用连接池

  • 这看起来像是预处理语句缓存的某种问题。除非您能在代码中发现PreparedStmt或ResultSet处理的其他错误(其前景并不明显),否则1)和2)最有可能提供解决方案/或特定的解决方法。

    您如何知道
    closeDBConnection()
    正在被调用?把一些日志放进去。由于您没有显示该代码,很可能是重复调用了
    model()
    构造函数,但由于代码中的某些缺陷,连接被泄漏或未关闭。我将closeDbConnection()放在了抓取程序的末尾。我在主类中创建了一个模型,每个线程都使用该模型。在抓取了我需要的东西之后,我在单个模型上调用closeDBConnection。这是错误的吗?您在connect.close()上引入了一个潜在的NPE,您必须检查null。此外,关闭语句和结果集也是一种很好的做法,其顺序与获得它们的顺序相反,即使通常在关闭连接时自动关闭。忽略异常也不是一个好主意。一个显而易见的假设&跳转到的常见错误,但“Eclipse内存分析器”或“累积对象”堆报告显然不支持它——它们只表示一个JDBC4Connection实例。他在评论中还表示,他只创建了一个带有一个连接的“模型”,并分享了这一点。@ThomasW我不认为凯文声称存在多个连接实例,他只是说它没有关闭。在关闭连接时,从连接中获得的其他资源也应该被释放,因此我认为它应该解决语句堆积的问题。编辑后仍然不正确——尽快返回连接只有在连接被合并时才有助于提高性能。在没有池的情况下关闭和重新打开会给每条语句带来连接设置开销(非常昂贵)。@eis--Kevin很好,但这次他看到的是“明显的”问题,而不是“实际的”问题。他所宣称的是他所宣称的——而不是关于每一次stmt关闭连接的好处的一般性的空谈(这是不正确的)。开发人员需要解决“实际”问题,这就是为什么我的答案建议尝试关闭和重新打开——但只能每1000条语句一次。我还建议调查另外两个可能的领域。我的解决方案旨在解决/解决精确的问题,而不会造成不必要的性能损失。这很好。我使用了修复编号2),我的程序现在开始运行!!!Kevin的解决方案不好,因为我的性能急剧下降(在我可以每秒下载6页之前,我可以每秒下载0,5页,因为每次写操作打开和关闭连接都需要时间)。非常感谢。尽管JDBC驱动程序可能仍然存在缺陷。。如果您尝试其他版本,它可能会被修复。
    public class model {
    
        public synchronized void insertCat(String parola, String categoria){
            Connection connect = null;
            try{
                Class.forName("com.mysql.jdbc.Driver");
                connect = DriverManager.getConnection("jdbc:mysql://localhost/system?user=keyword_tool&password=l0gripp0");
                PreparedStatement statement = connect.prepareStatement("insert into sostantivi (nome, categoria) values (?, ?)");
                statement.setString(1, parola);
                statement.setString(2, categoria);
    
                statement.executeUpdate();
                statement.close();
    
            } catch (Exception e){
                //System.out.println(e);
            }finally{
               if(connect != null){
                   try {
                      connect.close();
                   } catch (Exception e) {
                      System.out.println(e);
                   }
               }
            }
    
        }
    
    }