2013-05-31 2 views
1

을 업로드하려고하지만, 하나의 비디오를 업로드 한 후 나는 오류가 아래에있어 : ​​java.lang.OutOfMemoryError와 : Java 힙 공간 : 내가 바람둥이 서버에서 동영상을 업로드하려고 비디오를

오류 로그 :

org.apache.jasper.JasperException: An exception occurred processing JSP page /SaveVideos.jsp at line 34 

31:   pos = file.indexOf("\n", pos) + 1; 
32:   int boundaryLocation = file.indexOf(boundary, pos) - 4; 
33:   int startPos = ((file.substring(0, pos)).getBytes()).length; 
34:   int endPos = ((file.substring(0, boundaryLocation)).getBytes()).length; 
35:   
36:  // String pathToFile = this.getServletContext().getRealPath(request.getPathInfo()); 
37:   File ff = new File(this.getServletContext().getRealPath("/")+"videos/"+ saveFile); 


Stacktrace: 
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:524) 
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:417) 
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320) 
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803) 


root cause 

javax.servlet.ServletException: java.lang.OutOfMemoryError: Java heap space 
    org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:850) 
    org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:779) 
    org.apache.jsp.SaveVideos_jsp._jspService(SaveVideos_jsp.java:138) 
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803) 
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393) 
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320) 
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803) 


root cause 

java.lang.OutOfMemoryError: Java heap space 
    java.lang.StringCoding$StringEncoder.encode(StringCoding.java:232) 
    java.lang.StringCoding.encode(StringCoding.java:272) 
    java.lang.StringCoding.encode(StringCoding.java:284) 
    java.lang.String.getBytes(String.java:987) 
    org.apache.jsp.SaveVideos_jsp._jspService(SaveVideos_jsp.java:90) 
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803) 
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393) 
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320) 
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803) 

SaveVideo.jsp :

<%@ page import="java.io.*,java.sql.*,java.util.zip.*"%> 
<%@ page import="jdbc.DBConnection"%> 
<% 
    String saveFile = ""; 
    String contentType = request.getContentType(); 
    if ((contentType != null) 
      && (contentType.indexOf("multipart/form-data") >= 0)) { 
     DataInputStream in = new DataInputStream(request 
     .getInputStream()); 
     int formDataLength = request.getContentLength(); 
     byte dataBytes[] = new byte[formDataLength]; 
     int byteRead = 0; 
     int totalBytesRead = 0; 
     while (totalBytesRead < formDataLength) { 
      byteRead = in.read(dataBytes, totalBytesRead, 
      formDataLength); 
      totalBytesRead += byteRead; 
     } 
     String file = new String(dataBytes); 
     saveFile = file.substring(file.indexOf("filename=\"") + 10); 
     saveFile = saveFile.substring(0, saveFile.indexOf("\n")); 
     saveFile = saveFile.substring(saveFile.lastIndexOf("\\") + 1, 
     saveFile.indexOf("\"")); 
     int lastIndex = contentType.lastIndexOf("="); 
     String boundary = contentType.substring(lastIndex + 1, 
     contentType.length()); 
     int pos; 
     pos = file.indexOf("filename=\""); 
     pos = file.indexOf("\n", pos) + 1; 
     pos = file.indexOf("\n", pos) + 1; 
     pos = file.indexOf("\n", pos) + 1; 
     int boundaryLocation = file.indexOf(boundary, pos) - 4; 
     int startPos = ((file.substring(0, pos)).getBytes()).length; 
     int endPos = ((file.substring(0, boundaryLocation)).getBytes()).length; 

    // String pathToFile = this.getServletContext().getRealPath(request.getPathInfo()); 
     File ff = new File(this.getServletContext().getRealPath("/")+"videos/"+ saveFile); 

     FileOutputStream fileOut = new FileOutputStream(ff); 
     fileOut.write(dataBytes, startPos, (endPos - startPos)); 
     fileOut.flush(); 
     fileOut.close(); 
%><br> 
<table border="2"> 
    <tr> 
     <td><b>You have successfully upload the file:</b> <% 
     response.sendRedirect("HomePage.jsp"); 

%> 
     </td> 
    </tr> 
</table> 
<% 
DBConnection db_con = new DBConnection(); 
PreparedStatement psmnt = null; 
     try { 
      Connection con = db_con.getConnection(); 

       psmnt = con.prepareStatement("insert into video_tbl(Video_name ) values(?)"); 

      psmnt.setString(1,saveFile); 

      int s = psmnt.executeUpdate(); 
      if (s > 0) { 
     System.out.println("Uploaded successfully !"); 
      } else { 
     System.out.println("Error!"); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
%> 

구성

VM Arguments : 
-Xms1024m -Xmx1024m 
+4

왜 업로드를 메모리에 스트리밍하지 않고 디스크로 스트리밍하지 않을까요? 이 작업을 수행 할 수있는 많은 프레임 워크가 있습니다. 또는, 귀하의 경우에는'while (totalBytesRead Rup

답변

6

코드와 관련된 두 문제가 있습니다

  1. 당신은 메모리에 전체 업로드 된 문서 (비디오) 버퍼링된다. 이것은 많은 메모리를 필요로하며 귀하의 OOME의 가장 큰 원인입니다.

  2. 포함한 FileContent 이상 2^32 - 1 바이트 인 경우, 이전에 관련 (즉, 2 기가 바이트 이상의 비트) 컨텐츠 길이가 int에 적합하지 않기 때문에 코드가 실패합니다, 당신은보다 더와 배열을 할당 할 수 없습니다 2^32 - 1 요소.

    • 감싸고 InputStreamBufferedInputStream 아닌 DataInputStream에서 : 당신이해야 할 일은

이 같은 것입니다.

  • 개행 문자에 도달 할 때까지 read()을 사용하여 양식 데이터 "봉투"데이터를 한 번에 한 바이트 씩 읽고 누적하십시오. 그런 다음 구문 분석을 수행 할 각 행을 문자열로 바꿉니다.
  • 파일 내용의 시작 부분에 도달했으면 한 번에 한 바이트 씩 경계 시퀀스를 찾고 BufferedOutputStream을 통해 출력 파일에 (경계가 아닌) 데이터 바이트를 씁니다.

  • 더 나은 아직, 당신은 멀티 파트를 처리하기 위해 기존 구성 요소를 찾을 수 있어야 보았다합니다.


    "scriptlet"코드로 JSP에 중요한 "비즈니스 로직"이 포함되어 있다는 문제가 있습니다. 이것은 나쁜 습관입니다. 서블릿에서 비즈니스 로직 (데이터베이스 쿼리 및 업데이트, 파일 업로드 등)을 수행하고 출력 렌더링을 위해 JSP를 사용해야합니다.

    0

    비디오를 두 번 메모리에 만듭니다. 1. byte dataBytes [] = new byte [formDataLength]; 2. 문자열 파일 = 새 문자열 (dataBytes);

    당신은 그것을 변경할 수 있습니다 ... 그것은 직접 파일 입력 스트림에서 스트림 있도록

    3

    당신은 당신의 코드를 다시 작성할 수 있습니다. 이것은 단지 작은 버퍼를 필요로합니다.

    관련 문제