2012-01-12 72 views
1

我想讀含有換行符separted 158000條記錄(12MB)的文件,並把該記錄在MySQL數據庫中,但周圍插入後49000記錄我的Java程序引發以下將所述數據錯誤發生的歷史:: java.lang.OutOfMemoryError:Java堆空間

FileInputStream file; 
     DataInputStream dataIn; 
     BufferedReader bReader; 
     Connection conn= openConnection(); 
     String strRecord=new String(); 
     String[]strSplittedRecord; 
     file= new FileInputStream("D:\\Java\\CountryWhois.txt"); 
     dataIn= new DataInputStream(file); 
     bReader= new BufferedReader(new InputStreamReader(dataIn)); 
     PreparedStatement insertStmt; 
     String strQuery="insert into countrywhois values(?,?,?,?,?,?)"; 
     while((strRecord=bReader.readLine())!=null) 
     { 

      strSplittedRecord=strRecord.split(","); 

     try { 

      insertStmt=conn.prepareStatement(strQuery); 
      insertStmt.setString(1,strSplittedRecord[0].substring(1, strSplittedRecord[0].length()-1)); 
      insertStmt.setString(2,strSplittedRecord[1].substring(1, strSplittedRecord[1].length()-1)); 
      insertStmt.setString(3,strSplittedRecord[2].substring(1, strSplittedRecord[2].length()-1)); 
      insertStmt.setString(4,strSplittedRecord[3].substring(1, strSplittedRecord[3].length()-1)); 
      insertStmt.setString(5,strSplittedRecord[4].substring(1, strSplittedRecord[4].length()-1)); 
      insertStmt.setString(6,strSplittedRecord[5].substring(1, strSplittedRecord[5].length()-1)); 
      int nResultInsert=insertStmt.executeUpdate(); 
      if(nResultInsert!=0) 
      { 
       System.out.println("Inserted 1"); 


      } 
      else 
      { 
       if(conn!=null) 
       { 
        conn.close(); 
        System.out.println("Disconnected from database"); 
       } 
      } 
     } 
     catch (Exception e) 
     { 
      conn.close(); 
      e.printStackTrace(System.out);   
     } 

     } 

它在線路的insertstmt = conn.prepareStatement(strQuery)拋出異常的異常

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
    at java.util.jar.Manifest$FastInputStream.<init>(Manifest.java:315) 
    at java.util.jar.Manifest$FastInputStream.<init>(Manifest.java:310) 
    at java.util.jar.Manifest.read(Manifest.java:178) 
    at java.util.jar.Manifest.<init>(Manifest.java:52) 
    at java.util.jar.JarFile.getManifestFromReference(JarFile.java:167) 
    at java.util.jar.JarFile.getManifest(JarFile.java:148) 
    at sun.misc.URLClassPath$JarLoader$2.getManifest(URLClassPath.java:696) at sun.misc.URLClassPath$JarLoader$2.getManifest(URLClassPath.java:696) 

    at java.net.URLClassLoader.defineClass(URLClassLoader.java:228) 
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:430) at com.mysql.jdbc.Util.handleNewInstance(Util.java:430) 

    at com.mysql.jdbc.PreparedStatement.getInstance(PreparedStatement.java:553) 
    at com.mysql.jdbc.ConnectionImpl.clientPrepareStatement(ConnectionImpl.java:1378) 
    at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4143) 
    at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4042) 
    at loadcsvdatabase.LoadCsvDatabase.fnLoadCsvIntoMemory(LoadCsvDatabase.java:52) 
    at loadcsvdatabase.LoadCsvDatabase.main(LoadCsvDatabase.java:29) 

Java代碼

爲什麼我的程序運行內存溢出異常請建議我..

回答

7

你正在創建每次插入一條記錄時一個新的預處理。這不是PreparedStatements應該如何使用。此外,你永遠不會關閉創建的PreparedStatement,這可能會導致OutOfMemoryException異常,但這不是問題的根源。

您必須只能創建一個PreparedStatement和重用。然後,在插入所有記錄後,關閉PreparedStatement和Connection。

+2

這是另外一點可以addBatch提高性能。 – 2012-01-12 06:34:34

+0

我第二個庫庫巴赫。但首先Nishit必須在優化之前先解決OOM問題。此外,由於大尺寸的記錄,他需要限制addBatch調用100(IMO),每1則ExecuteBatch()調用。 – 2012-01-12 07:04:03

+0

謝謝你們!這是錯誤我是通過將事先準備好的聲明while循環 – 2012-01-12 07:30:54

0
insertStmt=conn.prepareStatement(strQuery); 

應該在while循環之外。把它究竟初始化strQuery

+0

由於它炒菜鍋裏面做的! – 2012-01-12 08:07:05

0

你應該修改代碼以遵循這種方式後:

... 

try { 
    Connection conn = openConnection(); 
    try { 

    String strQuery="insert into countrywhois values(?,?,?,?,?,?)"; 
    PreparedStatement insertStmt=conn.prepareStatement(strQuery); 
    while (...) { 
     try { 
      .... 
      int nResultInsert=insertStmt.executeUpdate(); 

      // handle your result here (e.g. print/log) 
      // DO NOT close() here, continue with loop 

     } catch (Exception e) { 
      // handle your exception here (e.g. print/log) 
      // DO NOT close() here, continue with loop, OR break loop 
     } 
    } 

    } finally { 
     // closing SQL Connection no matter what happens to your while-loop 
     conn.close(); 
    } 
} catch (Exception e) { 
    // handle your exception here (e.g. print/log) 
} 
+0

謝謝!有用 – 2012-01-12 07:32:05

相關問題