2011-08-23 81 views
1

我有这个代码压缩文件夹,但是当我压缩大文件夹(10GB)时,出现内存错误。它适用于1GB左右的文件夹。压缩 - java.lang.OutOfMemoryError:Java堆空间

可能是一些内存泄漏,但在我的代码泄漏?我怎样才能解决这个问题?

谢谢。

这是错误:

Exception in thread "main" java.lang.reflect.InvocationTargetException 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
at  sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
at java.lang.reflect.Method.invoke(Method.java:597) 
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56) 
Caused by: java.lang.OutOfMemoryError: Java heap space 
at java.util.Arrays.copyOf(Arrays.java:2882) 
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100) 
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:572) 
at java.lang.StringBuilder.append(StringBuilder.java:203) 
at java.io.UnixFileSystem.resolve(UnixFileSystem.java:93) 
at java.io.File.<init>(File.java:207) 
at java.io.File.listFiles(File.java:1056) 
at Zipper.addDir(Zipper.java:27) 
at Zipper.addDir(Zipper.java:32) 
at Zipper.addDir(Zipper.java:32) 
at Zipper.addDir(Zipper.java:32) 
at Zipper.addDir(Zipper.java:32) 
at Zipper.addDir(Zipper.java:32) 
at Zipper.addDir(Zipper.java:32) 
at Zipper.addDir(Zipper.java:32) 
at Zipper.addDir(Zipper.java:32) 
at Zipper.zipDir(Zipper.java:17) 
at Schedule.runBackup(Schedule.java:128) 
at Machine.runBackup(Machine.java:108) 
at Person.main(Person.java:51) 

这是代码:

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipOutputStream; 

import javax.swing.JFrame; 
import javax.swing.JOptionPane; 

public class Zipper { 

static void zipDir(String zipFileName, String dir) throws Exception { 
    File dirObj = new File(dir); 
    try { 
     ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName)); 
     addDir(dirObj, out); 
     out.close();  
    } catch(Exception e) { 
     JFrame frame = new JFrame(); 
     JOptionPane.showMessageDialog(frame, e.getMessage() + ". Is settings.xml correct?"); 
    } 
} 

static void addDir(File dirObj, ZipOutputStream out) throws IOException { 
    try { 
     File[] files = dirObj.listFiles(); 
     byte[] tmpBuf = new byte[1024]; 
     for (int i = 0; i < files.length; i++) { 
      try { 
       if (files[i].isDirectory()) { 
        addDir(files[i], out); 
        continue; 
       } 
       FileInputStream in = new FileInputStream(files[i].getAbsolutePath()); 
       out.putNextEntry(new ZipEntry(files[i].getAbsolutePath().replace(File.separatorChar,'/'))); 
       int len; 
       while ((len = in.read(tmpBuf)) > 0) { 
        try { 
         out.write(tmpBuf, 0, len); 
        } 
        catch(Exception e) { 
         System.out.println(e.getMessage()); 
        } 
       } 
       out.closeEntry(); 
       in.close(); 
      } 
      catch(Exception e) { 
       System.out.println(e.getMessage()); 
      } 
     } 
    } 
    catch(Exception e) { 
     System.out.println(e.getMessage()); 
    } 
} 
} 
+0

什么是您的jdk版本?我问的原因是在jdk 1.4中有一个[JIRA](http://bugs.sun.com/bugdatabase/view_bug.do;:YfiG?bug_id=4705373)。 – CoolBeans

回答

0

如前所述,检查堆大小,虽然你可能有它设置足够高的,如果1GB是确定的。 考虑到您处理10GB的未压缩数据,请不要忘记zip格式的限制:存档的最大大小为4GB(如果您不使用zip64)。我不知道这是否与你的情况有关,但它可能只是做。

作为一个附注,总是close()流内finally

0

如果你正在泄漏,有很多工具可以跟踪它(例如jmap + jhat)。

但是,您的问题可能不是泄漏。你的目录有多大?在listFiles中发生异常,所以如果你有一个非常大的目录(或者一组目录,因为你正在使用递归遍历),也许你只是有太多的文件。正如@CoolBeans所说,你可能只需要调整你的堆空间参数。

+0

因为他使用'FileOutputStream',太多的数据不应该成为问题,所以流不会保存在内存中。但也许他有一个大量的文件,不知何故它只是弹出... –

+0

这就是我的意思;我编辑了我的帖子,以防其他人感到困惑。感谢您指出了这一点。 – jdigital

+0

对于listFiles(),数据的大小并不重要,但是文件的数量并不重要。如果目录中有很多小文件,这将触发OOME而不管它们的大小,因为listFiles()需要在返回之前构建所有文件名的数组。 – prunge

相关问题