2011-08-23 4 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

, 당신은 아마 1 기가 바이트 확인하는 경우는 충분히 높게 설정되어 있지만, 힙 크기를 확인

는 오류입니다. 10GB의 압축되지 않은 데이터를 처리하는 것을 고려하면 zip 형식의 한계를 잊지 마십시오. 4GB의 아카이브 크기 (zip64를 사용하지 않는 경우). 이것이 귀하의 사건과 관련이 있는지는 모르지만 다만 그렇게 할 수 있습니다.

보조 메모로 항상 close() 개의 스트림이 finally 안에 있습니다.

0

유출 된 경우 jmap + jhat와 같이 추적 할 수있는 도구가 많이 있습니다.

그러나 문제는 누출이 아닐 수 있습니다. 디렉토리가 얼마나 큽니까? 예외가 listFiles에서 발생했기 때문에 매우 큰 디렉토리 (또는 재귀 적 탐색을 사용하기 때문에 디렉토리 집합)가 있으면 파일이 너무 많을 수 있습니다. @CoolBeans가 말했듯이, 힙 공간 매개 변수를 조정하면됩니다.

+0

너무 많은 데이터가'FileOutputStream'을 사용하기 때문에 문제가되지 않아야합니다. 스트림은 메모리에 보관되지 않습니다. 하지만 어쩌면 그는 엄청난 양의 파일을 가지고 있고 어쨌든 그냥 갑자기 나타납니다. –

+0

그게 무슨 뜻입니까; 다른 사람이 혼란 스러울 경우를 대비하여 내 게시물을 편집했습니다. 이것을 지적 해 주셔서 감사합니다. – jdigital

+0

listFiles()의 경우 데이터의 크기는 중요하지 않지만 파일 수는 다릅니다. 디렉토리에 작은 파일이 많이있는 경우, listFiles()는 모든 파일 이름의 배열을 반환해야하기 때문에 크기에 관계없이 OOME을 트리거합니다. – prunge

관련 문제