2015-01-21 130 views
0

我想在MySql dB中只包含2列(id,说明)添加50000数据。但是我能够添加至30000点的数据,但是当它试图增加更多的DATAS它给了我下面的错误Java堆空间::内存不足错误

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
    at java.util.Arrays.copyOf(Unknown Source) 
    at java.util.Arrays.copyOf(Unknown Source) 
    at java.util.ArrayList.grow(Unknown Source) 
    at java.util.ArrayList.ensureExplicitCapacity(Unknown Source) 
    at java.util.ArrayList.ensureCapacityInternal(Unknown Source) 

我自己也尝试下运行配置VM参数添加参数。还试着改变weblogic> bin中的setDomainEnv.cmd .Below是代码。任何人谁可以帮我这个::

public class SequenceGenerator { 
    private static final String CHAR_LIST = 
      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; 
    private static final int RANDOM_STRING_LENGTH = 5; 

    private static final String jsonFilePath ="D:/Assignments/Sequence/file.json"; 
    static HashMap hm = new HashMap(); 
    static Set mapSet = null; 
    int count=1; 
    /** 
    * This method generates random string 
    * and stores the values in a hashmap 
    */ 
    public void generateRandomString(){ 


     while(count<=50000){/*Change 10000 to 30000*/ 
      StringBuffer randStr = new StringBuffer(); 
      for(int i=0; i<RANDOM_STRING_LENGTH; i++){ 
       int number = getRandomNumber(); 
       char ch = CHAR_LIST.charAt(number); 
       randStr.append(ch); 
      } 
      hm.put(count, randStr); 
      mapSet = hm.entrySet(); 
      //System.out.println(randStr.toString()); 
      count++; 
     } 

    } 

    /** 
    * This method generates random numbers 
    * @return int 
    */ 
    private int getRandomNumber() { 
     int randomInt = 0; 
     Random randomGenerator = new Random(); 
     randomInt = randomGenerator.nextInt(CHAR_LIST.length()); 
     if (randomInt - 1 == -1) { 
      return randomInt; 
     } else { 
      return randomInt - 1; 
     } 
    } 

    public static DataSource getMySQLDataSource() throws Exception { 
     Properties props = new Properties(); 
     FileInputStream fis = null; 
     MysqlDataSource mysqlDS = null; 

     try { 
      fis = new FileInputStream("D:/Assignments/Sequence/db.properties"); 
     } catch (FileNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     props.load(fis); 
     mysqlDS = new MysqlDataSource(); 
     mysqlDS.setURL(props.getProperty("MYSQL_DB_URL")); 
     mysqlDS.setUser(props.getProperty("MYSQL_DB_USERNAME")); 
     mysqlDS.setPassword(props.getProperty("MYSQL_DB_PASSWORD")); 
     return mysqlDS; 
    } 

    public static void main(String[] args) throws Exception 
    { 
     SequenceGenerator sg = new SequenceGenerator(); 
     sg.generateRandomString(); 
     System.out.println("Current size of Heap::"+Runtime.getRuntime().totalMemory()); 
     System.out.println("Max size of Heap::"+Runtime.getRuntime().maxMemory()); 
     Connection con = null; 
     Statement stmt = null; 
     ResultSet rs = null; 
     PreparedStatement pst = null; 
     FileWriter fw = new FileWriter(jsonFilePath); 
     try { 
      con = getMySQLDataSource().getConnection(); 
      stmt = con.createStatement(); 
      System.out.println("Displaying key and value pair of HashMap.."); 
      Iterator mapIterator = mapSet.iterator(); 
      while(mapIterator.hasNext()) 
      { 
       Map.Entry mapEntry = (Map.Entry)mapIterator.next(); 
       //int key = Integer.parseInt(mapEntry.getKey().toString()); 
       //String value = mapEntry.getValue().toString(); 
       pst = con.prepareStatement("insert into nodes_test values (?,?)"); 
       pst.setInt(1, Integer.parseInt(mapEntry.getKey().toString())); 
       pst.setString(2, mapEntry.getValue().toString()); 
       pst.executeUpdate(); 
       System.out.println(Integer.parseInt(mapEntry.getKey().toString())); 
      } 
      fw.close(); 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     }finally{ 
      try { 
       if(rs != null) rs.close(); 
       if(stmt != null) stmt.close(); 
       if(pst != null) pst.close(); 
       if(con != null) con.close(); 
       System.out.println("Free Memory::"+Runtime.getRuntime().freeMemory()); 
      } catch (SQLException e) { 
       e.printStackTrace(); 
      } 
     } 

    } 

} 
+0

您可以对每500个插入进行一次批量更新,并在每个批次之后引入睡眠,以便JVM可以收集垃圾值。同时增加JVM堆空间。 – 2015-01-21 06:36:27

+0

Sid..CAn u请详细解释 – Soumya 2015-01-21 06:38:09

+1

您应该在java中使用批处理执行,以便可以批量插入。以下是示例https://my.vertica.com/docs/4.1/HTML/Master/14878.htm。您可以使用addBatch()添加每个插入,并且在每个500条目之后,您应该执行executeBatch(),以便将其作为批量插入插入到db中。在每个executeBatch()之后,您应该提供2秒的睡眠时间,以便JVM释放循环使用的所有内存。 – 2015-01-21 06:48:09

回答

0


使用停止浪费记忆。只需将生成的值直接写入数据库即可。

这是您的代码,没有不必要的内存使用情况。我没有做其他尝试来优化代码。

public class SequenceGenerator 
{ 
    private static final String CHAR_LIST = 
     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; 
    private static final int RANDOM_STRING_LENGTH = 5; 
    private static final Random RANDOM = new Random(); 

    /** 
    * Generates and returns a random string 
    */ 
    public String generateRandomString() { 
     char[] chars = new char[RANDOM_STRING_LENGTH]; 
     for (int i = 0; i < RANDOM_STRING_LENGTH; i++) { 
      int number = RANDOM.nextInt(CHAR_LIST.length()); 
      chars[i] = CHAR_LIST.charAt(number); 
     } 
     return new String(chars); 
    } 

    public static DataSource getMySQLDataSource() throws Exception { 
     Properties props = new Properties(); 
     MysqlDataSource mysqlDS = null; 

     FileInputStream fis = new FileInputStream(
       "D:/Assignments/Sequence/db.properties"); 
     try { 
      props.load(fis); 
     } finally { 
      fis.close(); 
     } 
     mysqlDS = new MysqlDataSource(); 
     mysqlDS.setURL(props.getProperty("MYSQL_DB_URL")); 
     mysqlDS.setUser(props.getProperty("MYSQL_DB_USERNAME")); 
     mysqlDS.setPassword(props.getProperty("MYSQL_DB_PASSWORD")); 
     return mysqlDS; 
    } 

    public static void main(String[] args) throws Exception { 
     SequenceGenerator sg = new SequenceGenerator(); 
     Connection con = getMySQLDataSource().getConnection(); 
     try { 
      PreparedStatement pst = con.prepareStatement("insert into nodes_test values (?,?)"); 
      for (int i = 0; i < 50000; i++) { 
       pst.setInt(1, i); 
       pst.setString(2, sg.generateRandomString()); 
       pst.executeUpdate(); 
       System.out.println(i); 
      } 
      pst.close(); 
     } finally { 
      con.close(); 
     } 
    } 
} 
+0

感谢它工作正常..你可以帮我优化这段代码。 – Soumya 2015-01-21 09:22:37

1

我会建议存储字符串,只要他们生成,而不是存储在一个HashMap。如果您在保存后未保存应用程序中的数据,请避免使用内存。

您可以在generateRandomString()方法中引入一个Connection参数,并从main()方法传递它。随机字符串一旦创建,您就可以根据连接调用存储。此外,我会尝试重用准备好的声明。

0

先找出使用堆内存下面的代码

如果使用下面的环境变量现在
public static void main(String[]args){ 

    long totalHeapSize = Runtime.getRuntime().totalMemory(); 

    //Total heap size 
    System.out.println("Total Heap Size is: " + totalHeapSize); 
} 

更改堆大小

SET _JAVA_OPTIONS = -Xms512m -Xmx1024m 

或以下命令

java -Xms512m -Xmx1024m TestData.java