2010-02-25 7 views
2

선택 필드를 표시하기 위해 처리를 위해 80,193KB FITS 파일을 업로드 할 때 추적에서 아래에 설명 된 오류가 발생했습니다. 기본적으로 나는 사용자가 업로드 및 처리를 위해 최대 6 개의 FITS 파일을 선택할 수있는 모의 웹 인터페이스를 가지고 있습니다. 두 개의 [다른] FITS 파일 (각각 약 54,574KB)을 처리를 위해 이동 중에 업로드하면 오류가 발생하지 않습니다. 필드는 콘솔에 표시되거나 인쇄됩니다. 그러나 하나의 80,193KB 파일을 업로드 할 때 아래 오류가 발생합니다. 어떻게 해결합니까?java.lang.OutOfMemoryError : Java 힙 공간

나는 처음 반복 계산 비싼 것을 생각하지만 난 80메가바이트 파일의 readHDU를 호출에이 occcurs 의심 : I 효율적으로 해결하기를 해결하려면 어떻게

while ((newBasicHDU = newFits.readHDU()) != null) { 

를? 나는 7 건배

Windows에서 프로그램을 실행 해요

추적 :

SEVERE: Servlet.service() for servlet FitsFileProcessorServlet threw exception 
java.lang.OutOfMemoryError: Java heap space 
    at java.lang.reflect.Array.multiNewArray(Native Method) 
    at java.lang.reflect.Array.newInstance(Unknown Source) 
    at nom.tam.util.ArrayFuncs.newInstance(ArrayFuncs.java:1028) 
    at nom.tam.fits.ImageData.read(ImageData.java:258) 
    at nom.tam.fits.Fits.readHDU(Fits.java:573) 
    at controller.FITSFileProcessor.processFITSFile(FITSFileProcessor.java:79) 
    at controller.FITSFileProcessor.doPost(FITSFileProcessor.java:53) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849) 
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) 
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454) 
    at java.lang.Thread.run(Unknown Source) 

코드 : 톰캣에 충분한 메모리를 할당되지 않은 것 같은

/** 
    * 
    * @param 
    * @return 
    */ 
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { 

     // Check that we have a file upload request 
     boolean isMultipart = ServletFileUpload.isMultipartContent(request); 

     if (isMultipart) { 

      Fits newFits = new Fits(); 
      BasicHDU newBasicHDU = null; 
      ServletFileUpload upload = new ServletFileUpload();      // Create a new file upload handler 

      // Parse the request 
      try { 
       //List items = upload.parseRequest(request);      // FileItem 
       FileItemIterator iter = upload.getItemIterator(request); 

       // iterate through the number of FITS FILES on the Server 
       while (iter.hasNext()) { 
        FileItemStream item = (FileItemStream) iter.next(); 
        if (!item.isFormField()) { 
         this.processFITSFile(item, newFits,newBasicHDU); 
        } 
       } 
      } catch (FileUploadException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      }  
     } 
    } 

    /** 
    * 
    * @param 
    * @return 
    */ 
    public void processFITSFile(FileItemStream item, Fits newFits, BasicHDU newBasicHDU) throws IOException { 

     // Process the fits file 
     if (!item.isFormField()) { 
      String fileName = item.getName();          //name of the FITS File 
      try { 
       System.out.println("Fits File Fields Printout: " + fileName); 
       InputStream fitsStream = item.openStream();        
       newFits = new Fits(fitsStream); 
       System.out.println("number of hdu's if: " + newFits.getNumberOfHDUs()); 

       while ((newBasicHDU = newFits.readHDU()) != null) {    //line 76 
        System.out.println("Telescope Used: " + newBasicHDU.getTelescope()); 
        System.out.println("Author: " + newBasicHDU.getAuthor()); 
        System.out.println("Observer: " + newBasicHDU.getObserver()); 
        System.out.println("Origin: " + newBasicHDU.getOrigin()); 
        System.out.println("End of Printout for: \n" + fileName); 
        System.out.println();    
       } 

       fitsStream.close(); 

      } catch (Exception e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     }  
    } 
+4

'-Xmx' 스위치를 사용하여 VM에서 사용할 수있는 힙 크기를 늘려 보았습니까? –

+2

사용하는 API가 반복자 스타일 액세스를 지원합니까? 즉 So java는 전체 파일을 처리 할 때 읽을 필요가 없으며 시간에 기록 만 남습니다. 그것이 당신이하고있는 것에 대한 옵션이 아니라면, 그렉의 제안에 따라 힙 크기를 늘려야 할 것입니다. – Mike

+0

아니요 아직 – Terman

답변

5

는 소리 - 당신은에 의해이 문제를 해결 할 수 있습니다 예를 들어 -Xmx512m을 지정하여 최대 512MB의 메모리를 할당합니다.

설정 방법에 대한 자세한 내용은 here을 참조하십시오.

2

RAM보다 많은 RAM을 사용하려고합니다.

프로그램을 시작할 때 -Xmx 플래그를 추가하여 최대 메모리를 늘려보십시오. 프로그램에 최대로 메모리 128 메가 바이트 할당합니다

java -Xmx128m youProgram 

.

+0

"프로그램에 128 메가 바이트의 메모리를 할당합니다"- JVM이 128m의 힙에 사용할 * 최대 * 크기를 설정합니다. 별도로 지정하지 않는 한 (-Xms로) 힙의 * 시작 * 크기는 여전히 기본값입니다. –

+0

그리고 시스템은 힙이 아닌 것들에 대해 힙보다 많은 양의 메모리를 사용합니다. 일반적으로 지정된 힙 크기에 대해 30-40MB가 표시됩니다. –

+0

오스카 - 일반적으로 그렇습니다. 그러나이 경우 포스터는 앱 서버 (Tomcat)를 사용하여 "정상적인"java -X 경로가 도움이되지 않을 수 있습니다. – Brian

0

java.lang.OutOfMemoryError는 JVM에서 할당 한 메모리를 초과했음을 의미합니다. -Xmx를 사용하여 JVM의 최대 메모리 힙 크기를 변경하십시오.

MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean(); 
System.out.println(memoryBean.getHeapMemoryUsage()); 
+0

올바르지 않음 - 최대 힙 크기를 변경하려면'-Xmx'를 사용하십시오. -Xms는 초기 힙 크기를 변경합니다. –

3

최저의 수정이 불필요하게 중복되지 않도록 코드를 강화하는 것입니다 :

당신이이 JVM 메모리의 크기 무엇인지 볼 수 있도록 할 수 있습니다 (당신에게 소프트웨어 원숭이 감사합니다) 데이터를 메모리에 저장합니다. stacktrace는 코드가 메모리의 파일 내용을 복제하려고 시도하고 있음을 나타냅니다. (제 3 자?) 코드를 향상시킬 수 없지만 대신에 을 처리하면이 즉시 처리하고 파일 공유를 구성/사용하여 업로드 된 파일을 메모리에 보관하지 않도록합니다. 대신 로컬 디스크 파일 시스템의 임시 저장소에 저장됩니다.

사용하려는 메모리를 최소화하려면 가능한 한 작은 임계 값 (기본값은 10KB)을 사용하십시오.

ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory()); 

이렇게하면 실제 처리에 충분한 메모리를 확보 할 수 있습니다.

여전히 힙 메모리 제한에 도달하면 다음 단계는 실제로 힙을 증가시킬 것입니다.

15

대부분의 답변은 힙 크기를 기본값 (64MB)에서 늘리는 것에 중점을두고 있습니다. 64MB는 54,574KB를 성공적으로 업로드 할 수있는 이유를 설명하고, 크기가 너무 작기 때문에 Tomcat과 프로그램은 부팅 할 때 10MB를 넘지 않습니다. 기억력을 높이는 것은 좋은 생각이지만, 실제로 질병이 아니라 증상을 치료하는 것입니다.

여러 명의 사용자가 큰 파일을 업로드하도록 허용하려는 경우 동시에 두 명의 사용자가 80MB 파일을 업로드하는 경우 160MB가 필요합니다. 그리고 3 명의 사용자가이 작업을 수행 할 경우 240MB가 필요합니다. 다음은 내가 제안하는 것입니다. 디스크에 쓰기 전에 RAM에이 물건을 읽지 않는 라이브러리를 찾으십시오. 그렇게하면 앱 규모가 커지고 이것이이 문제의 진정한 해결책입니다.

Jconsole (JDK와 함께 제공)을 사용하면 프로그램이 실행되는 동안 힙 크기를 볼 수 있습니다. Jconsole은 사용하기 쉽고 JVM을 사용하도록 구성 할 필요가 없습니다. 따라서 이러한 점에서 프로파일 러보다 훨씬 쉽지만 프로그램에 대한 자세한 정보는 얻을 수 없습니다. 그러나, 당신은 메모리의 세 부분을 더 잘 볼 수 있습니다 (Eden, Survivor, Tenured). JVM에 많은 메모리를 할당 했음에도 불구하고 때로는 이상한 것들로 인해 메모리 부족이 발생할 수 있습니다. JConsole이 그러한 것을 보여줄 것입니다.

관련 문제