none
Exception in thread “AWT-EventQueue-0” java.lang.OutOfMemoryError: Java heap space. RRS feed

  • Pergunta

  • Bom dia, prezados. Estou precisando de vossa ajuda. Tenho o método abaixo que selecciona e envia os dados para um servidor remoto. Ao enviar após algum tempo o cliente emite o seguinte erro:  Exception in thread “AWT-EventQueue-0” java.lang.OutOfMemoryError: Java heap space. Como resolver este problema? o que faço? 

    Estou utilizado o java e o sql server 2012

     public List<String> Pesquisa() {
            int i;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            
            List<String> listaDeRegisto = new ArrayList<>();
            Connection con = Conectar.getConnection();
            try {

                con.setAutoCommit(false);

                stmt = con.prepareStatement("select tipoEvento,         codigoClienteOld,    nomeClienteOld,       numeroFiscalClienteOld,   telefoneClienteOld,    emailClienteOld,   numeroCartaoCidadaoOld,            moradaOld,           codigoEncomendaOld,        dataEncomendaOld,  quantidadeLinhasDaEncomendaOld, codigoProdutoOld,         descricaoProdutoOld,         precoOld,              timeStampOld,              codigoClienteNew,          nomeClienteNew,       numeroFiscalClienteNew,   telefoneClienteNew,       emailClienteNew,       numeroCartaoCidadaoNew,        moradaNew,     codigoEncomendaNew,            dataEncomendaNew,          codigoProdutoNew,        quantidadeLinhasDaEncomendaNew,      descricaoProdutoNew,               precoNew,               timeStampNew,           sincVersao from LogOperacoes");

                rs = stmt.executeQuery();

                while (rs.next()) {

                    String c = (" insert into LogOperacoes(tipoEvento,     codigoClienteOld,    nomeClienteOld,   numeroFiscalClienteOld,   telefoneClienteOld,    emailClienteOld,   numeroCartaoCidadaoOld,        moradaOld,      codigoEncomendaOld,dataEncomendaOld,  quantidadeLinhasDaEncomendaOld,codigoProdutoOld,   descricaoProdutoOld,   precoOld,      timeStampOld,      codigoClienteNew,  nomeClienteNew,       numeroFiscalClienteNew,   telefoneClienteNew,       emailClienteNew,   numeroCartaoCidadaoNew,     moradaNew,     codigoEncomendaNew,dataEncomendaNew,          codigoProdutoNew,        quantidadeLinhasDaEncomendaNew,      descricaoProdutoNew,  precoNew,       timeStampNew,sincVersao)values('" + rs.getString(1) + "', " + rs.getInt(2) + ", '" + rs.getString(3) + "'," + rs.getInt(4) + ",'" + rs.getString(5) + "','" + rs.getString(6) + "','" + rs.getString(7) + "','" + rs.getString(8) + "'," + rs.getInt(9) + ",'" + rs.getTimestamp(10) + "'," + rs.getInt(11) + "," + rs.getInt(12) + ",'" + rs.getString(13) + "'," + rs.getDouble(14) + ",'" + rs.getTimestamp(15) + "'," + rs.getInt(16) + ",'" + rs.getString(17) + "'," + rs.getInt(18) + ",'" + rs.getString(19) + "','" + rs.getString(20) + "','" + rs.getString(21) + "','" + rs.getString(22) + "'," + rs.getInt(23) + ",'" + rs.getTimestamp(24) + "'," + rs.getInt(25) + "," + rs.getDouble(26) + ",'" + rs.getString(27) + "'," + rs.getDouble(28) + ",'" + rs.getTimestamp(29) + "'," + rs.getInt(30) + ")");
                    listaDeRegisto.add(c);

                }

                con.commit();

            } catch (SQLException ex) {
                System.out.println(ex.getMessage());
                return listaDeRegisto;
            } finally {

                Conectar.closeConnection(con, stmt, rs);

            }

            return listaDeRegisto;

        }

    quinta-feira, 12 de abril de 2018 08:57

Respostas

  • Orlando,

    Dois itens para prestar a atenção:

    • Você possui um con.commit() que para este código acima não faz diferença, uma vez que só está montando uma lista com os INSERTs, mas ainda não os executa;
    • De quantos registros estamos falando? Se forem dezenas/centenas de milhares ou milhões, sugiro que faça o INSERT em lotes menores (ex: se tiver 1 milhão de registros, divida em blocos de 1000 registros e faça um novo teste). É claro que isto depende do tamanho das informações que são concatenadas na string contendo o INSERT, então é preciso testar e ir otimizando.

    Juliano Nunes - http://linkedin.com/in/julianonunes

    Lembre-se de clicar em "Votar como útil" e "Marcar como Resposta" caso tenha respondido sua dúvida.

    Remember to "Vote as Helpful" and "Mark as Answer" if your question has been answered.

    quinta-feira, 12 de abril de 2018 10:33
  • Bom dia Orlando Cawende,

     acredito que sua query está incorreta, 

    veja que vc faz um select na tabela --select tipoEvento, codigoClienteOld ................... from LogOperacoes

    ou seja vc recupera a tabela inteira sem filtro algum

    e executa um  insert nela própria 

    insert into LogOperacoes .....................

    Assim para cadas execução  a tabela dobra de tamanho , isso está correto??

    1) sugiro que faça um procedure para resulver seu log ,assim diminue o trafego de rede.

    3) sugiro o estudo de BULK INSERT , com inserts a cada 1000 registros.



    Wesley Neves - Brasilia-DF     

    https://wesleyneves.wordpress.com/

    SELECT Tab.[that's me:]

    FROM

    (

        VALUES

            ('Wesley Neves'),

            ('Analista.NET'),

            ('Pós Graduando em Banco de Dados com ênfase em BI'),

            ('MTA -SQL Server'),

            ('MTA -Web Developed')

    ) AS Tab ("that's me:");


    "Se a resposta for útil ou ajudar ,não esqueça de marcar"





    Wesley Neves

    quinta-feira, 12 de abril de 2018 11:25
  • Você pode montar um INSERT com múltiplos registros no VALUES. Segue algoritmo de exemplo:

    String baseSql = "INSERT INTO Tabela(Coluna1, Coluna2,...) VALUES ";
    String sql = "";
    Integer registros = 0;
    
    while (rs.next()) {
      registros++;
    
      sql += "(" + rs.getInt(0) + "," + rs.getInt(1)),";
    
      if (registros == 1000) { // Para INSERT de 1000 registros por vez
        Statement statement = con.prepareStatement(baseSql + sql);
        statement.executeUpdate();
    
        registros = 0; // Início de um novo bloco
      }
    }
    
    if (registros > 0) {
      // Se sobraram registros a serem inseridos (sem alcançar o tamanho do bloco (1000 registros)
      Statement statement = con.prepareStatement(baseSql + sql);
      statement.executeUpdate();
    }


    Juliano Nunes - http://linkedin.com/in/julianonunes

    Lembre-se de clicar em "Votar como útil" e "Marcar como Resposta" caso tenha respondido sua dúvida.

    Remember to "Vote as Helpful" and "Mark as Answer" if your question has been answered.

    sexta-feira, 13 de abril de 2018 13:15
  • Deleted
    sexta-feira, 13 de abril de 2018 23:45

Todas as Respostas

  • Orlando,

    Dois itens para prestar a atenção:

    • Você possui um con.commit() que para este código acima não faz diferença, uma vez que só está montando uma lista com os INSERTs, mas ainda não os executa;
    • De quantos registros estamos falando? Se forem dezenas/centenas de milhares ou milhões, sugiro que faça o INSERT em lotes menores (ex: se tiver 1 milhão de registros, divida em blocos de 1000 registros e faça um novo teste). É claro que isto depende do tamanho das informações que são concatenadas na string contendo o INSERT, então é preciso testar e ir otimizando.

    Juliano Nunes - http://linkedin.com/in/julianonunes

    Lembre-se de clicar em "Votar como útil" e "Marcar como Resposta" caso tenha respondido sua dúvida.

    Remember to "Vote as Helpful" and "Mark as Answer" if your question has been answered.

    quinta-feira, 12 de abril de 2018 10:33
  • Bom dia Orlando Cawende,

     acredito que sua query está incorreta, 

    veja que vc faz um select na tabela --select tipoEvento, codigoClienteOld ................... from LogOperacoes

    ou seja vc recupera a tabela inteira sem filtro algum

    e executa um  insert nela própria 

    insert into LogOperacoes .....................

    Assim para cadas execução  a tabela dobra de tamanho , isso está correto??

    1) sugiro que faça um procedure para resulver seu log ,assim diminue o trafego de rede.

    3) sugiro o estudo de BULK INSERT , com inserts a cada 1000 registros.



    Wesley Neves - Brasilia-DF     

    https://wesleyneves.wordpress.com/

    SELECT Tab.[that's me:]

    FROM

    (

        VALUES

            ('Wesley Neves'),

            ('Analista.NET'),

            ('Pós Graduando em Banco de Dados com ênfase em BI'),

            ('MTA -SQL Server'),

            ('MTA -Web Developed')

    ) AS Tab ("that's me:");


    "Se a resposta for útil ou ajudar ,não esqueça de marcar"





    Wesley Neves

    quinta-feira, 12 de abril de 2018 11:25
  • Deleted
    sexta-feira, 13 de abril de 2018 10:00
  • Obrigado. 

    A quantidade de dados dependem do número de registos que serão operados o que pode atingir milhões de registos.

    como posso dividir os registos em lotes menores? 

    sexta-feira, 13 de abril de 2018 12:10
  • Agradecia o favor, poderia ser mais explicito quanto ao uso do  BULK INSERT , porque todos os exemplos que encontro na internet fazem referencia a documentos ou ficheiros do word, excel e access. Como fazer isso com uma tabela do  SQL server  não encontrei
    sexta-feira, 13 de abril de 2018 12:19
  • Obrigado Por responder minhas questões. Consegui realizar o linked server no entanto ficou a questão como saber que todos os dados colectado do cliente já se encontra no servidor remoto.   
    sexta-feira, 13 de abril de 2018 12:28
  • Você pode montar um INSERT com múltiplos registros no VALUES. Segue algoritmo de exemplo:

    String baseSql = "INSERT INTO Tabela(Coluna1, Coluna2,...) VALUES ";
    String sql = "";
    Integer registros = 0;
    
    while (rs.next()) {
      registros++;
    
      sql += "(" + rs.getInt(0) + "," + rs.getInt(1)),";
    
      if (registros == 1000) { // Para INSERT de 1000 registros por vez
        Statement statement = con.prepareStatement(baseSql + sql);
        statement.executeUpdate();
    
        registros = 0; // Início de um novo bloco
      }
    }
    
    if (registros > 0) {
      // Se sobraram registros a serem inseridos (sem alcançar o tamanho do bloco (1000 registros)
      Statement statement = con.prepareStatement(baseSql + sql);
      statement.executeUpdate();
    }


    Juliano Nunes - http://linkedin.com/in/julianonunes

    Lembre-se de clicar em "Votar como útil" e "Marcar como Resposta" caso tenha respondido sua dúvida.

    Remember to "Vote as Helpful" and "Mark as Answer" if your question has been answered.

    sexta-feira, 13 de abril de 2018 13:15
  • Deleted
    sexta-feira, 13 de abril de 2018 23:45