繁体   English   中英

为什么此功能会导致内存泄漏?

[英]Why does this function cause a memory leak?

public void filterLogins() throws IOException, SQLException{
    for(int i = 0; i<200; ++i){
        BufferedReader bufferedReader = new BufferedReader(new FileReader(folder + String.format("\\data\\part-%05d", i)));
        long prev_id = 0;
        boolean contains = false;
        while(bufferedReader.ready()){ //very big file
            String line = bufferedReader.readLine();
            Login login = new Login(line);
            if ( login.userId == prev_id && !contains )
                continue;
            if ( samples.contains(login.userId) ){
                mysql.execute("INSERT INTO ..."); // i think it doesn't matter in this case
                contains = true;
            }else{
                contains = false;
            }
            prev_id = login.userId;
        }
        bufferedReader.close();
        System.out.println((double)i/2.0);
    }
}

此功能可以长时间运行,因为数据是更大的文件。 2小时前,这是OutOfMemory异常的美眉

mysql是

public class MySQLHandler {
private Connection connection = null;
MySQLHandler() throws ClassNotFoundException, SQLException{
    try{
        Class.forName("com.mysql.jdbc.Driver");
        connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/database", "root", "");
    }catch (ClassNotFoundException e){
        System.out.println("Failed jdbc driver load.");
        throw e;
    }
}


public void close() throws SQLException{
       if ( connection != null)
           connection.close();
   }
   public boolean execute(String sql) throws SQLException{
       Statement statement = connection.createStatement();
       return statement.execute(sql);
   }
}

登录它只是带有数据的类。 (ID,名称,值等)。

似乎您是在每次创建Statement,而不是在循环中关闭该语句,这会导致内存泄漏。 执行完成后,关闭语句。

 public boolean execute(String sql) throws SQLException{
       Statement statement = connection.createStatement();
       return statement.execute(sql);
   }

喜欢

 public boolean execute(String sql) throws SQLException{
     Statement statement = null;
    try {
        statement = connection.createStatement();
        return statement.execute(sql);
    }finaly{
         if (statement != null) statement.close();
     }

UPDATE

正如@Holger在评论中提到的,如果您使用的是JDK 7及更高版本,则可以使用如下的try-with-resources

public boolean execute(String sql) throws SQLException{
       try(Statement s=connection.createStatement()) {
          return s.execute(sql);
       }
 }

尝试增加JVM的最大堆大小,例如:

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size
-Xss<size>        set java thread stack size

java -Xms16m -Xmx64m ClassName

还可以优化您的代码,并在使用后重用变量和关闭/清理。 例如:将它们移出循环:BufferedReader bufferedReader,String行和Login登录

public void filterLogins() throws IOException, SQLException{
    BufferedReader bufferedReader;
    long prev_id;
    boolean contains;
    String line;
    Login login;
    for(int i = 0; i<200; ++i){
        bufferedReader = new BufferedReader(new FileReader(folder + String.format("\\data\\part-%05d", i)));
        prev_id = 0;
        contains = false;
        while(bufferedReader.ready()){ //very big file
            line = bufferedReader.readLine();
            login = new Login(line);
            if ( login.userId == prev_id && !contains )
                continue;
            if ( samples.contains(login.userId) ){
                mysql.execute("INSERT INTO ..."); // i think it doesn't matter in this case
                contains = true;
            }else{
                contains = false;
            }
            prev_id = login.userId;
        }
        bufferedReader.close();
        System.out.println((double)i/2.0);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM