簡體   English   中英

java.lang.OutOfMemoryError:

[英]java.lang.OutOfMemoryError:

我正在嘗試從數據庫中檢索的字節創建視頻文件。 該計划在幾個小時之前運作良好。 上傳大文件后,當我嘗試檢索它時,它產生錯誤java.lang.OutOfMemoryError:

我的代碼是:

    conn = prepareConnection();
    StringBuilder sb=new StringBuilder(1024);
    sb.append("select videoname,videoid,videofull from ").append(uname.trim()).append("video");
    String sql=sb.toString();

    stmt = conn.prepareStatement(sql);
    ResultSet rs = stmt.executeQuery();

    while(rs.next()){
         byte[] videoData = rs.getBytes("videofull");       //#57
         int vid=rs.getInt("videoid");
         StringBuilder sb1 = new StringBuilder();
         sb1.append(vid);
         String videoid=sb1.toString();
         String vname=rs.getString("videoname");
         File file=new File("C:/Users/JamesPJ/Documents/skypark/skypark/WebContent/sp/resources/videos/"+vname+""+videoid+".mp4");

        if(file.exists() && !file.isDirectory()){
            continue;
        }
        else
        {
         FileOutputStream output = new FileOutputStream(file);
         IOUtils.write(videoData, output);
         output.close();
        }
       }
    request.setAttribute("uname", uname);
    RequestDispatcher dispatcher = request.getRequestDispatcher("/VideoList");
    if(dispatcher != null) {
        dispatcher.forward(request, response);
    } 

控制台輸出是:

Exception in thread "http-bio-8080-exec-3" java.lang.OutOfMemoryError: Java heap space
at oracle.sql.BLOB.getBytes(BLOB.java:217)
at oracle.jdbc.driver.T4CBlobAccessor.getBytes(T4CBlobAccessor.java:462)
at oracle.jdbc.driver.OracleResultSetImpl.getBytes(OracleResultSetImpl.java:716)
at oracle.jdbc.driver.OracleResultSet.getBytes(OracleResultSet.java:402)
at skypark.VideoFileCreator.doGet(VideoFileCreator.java:57)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:749)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:487)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:412)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:339)
at skypark.VideoStream.processRequest(VideoStream.java:48)
at skypark.VideoStream.doGet(VideoStream.java:64)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:931)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

請有人告訴我這個錯誤告訴了什么。 我需要糾正它.......謝謝.....

這里,

byte[] videoData = rs.getBytes("videofull");

您將整個文件內容存儲在服務器的內存中。 你知道, byte[]一個字節占用Java內存的一個字節。 如果你只有500MB內存並且文件超過500MB,那么你將得到這個錯誤。 請注意,當10個用戶同時請求50MB的視頻文件時,您也會得到它。 因此,如其他答案所示,增加Java內存只是一個臨時解決方案,並沒有經過深思熟慮。

您需要在InputStream風格中獲取它,以便在內部僅分配幾個(千字節)字節作為內存中的流緩沖區而不是整個文件內容。

InputStream videoData = rs.getBinaryStream("videofull");

然后使用IOUtils#copy()將其寫入所需的輸出流(不要忘記在finally中關閉它們!)。

FileOutputStream output = new FileOutputStream(file);
try {
    IOUtils.copy(videoData, output);
} finally {
    IOUtils.closeQuietly(output);
    IOUtils.closeQuietly(videoData);
}

由於視頻文件的大小很大,它已經完成了堆中的所有內存。 您必須通過將VM參數設置為-Xmx1024m來增加堆大小。 這會將堆空間增加到1 GB。 如果問題仍然存在,那么你必須使用java vm visual來分析你的程序的哪個部分正在消耗更多的內存,並且你可以通過其他方式來減少它。 增加堆空間超過1 gb並不是解決堆空間問題的好方法。

如果您從像eclipse這樣的IDE運行程序,請在運行配置模式下設置配置。

錯誤說你內存不足。 您需要將更少的內容加載到內存中,或者增加可用的內存總量。

錯誤告訴:

OutOfMemoryError: Java heap space

您需要更多堆空間:您可以將VM配置為使用更多堆空間。

選項-Xmx

示例: -Xmx256m ,最大堆空間為256 MB

使用-Xmx標志可以增加分配給JVM的堆空間。 -Xmx1500m例如。

如果從cli執行,這很容易

java -Xmx2000m youMainJavaFile

如果從eclipse或類似程序執行,則需要進入選項並告訴它在執行JVM時添加此標志。

Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector

Oracle文檔說,這意味着您應該增加運行程序的JVM的內存限制。 增加堆大小:

JVM_ARGS="-Xmx1024m"

這會將堆大小設置為1024mb。 或者您可以在IDE中執行此操作,在運行配置中給出-Xmx1024m因為VM參數將正常工作。

在IOUtils.write里面使用output.flush(),這樣緩沖的字節就會被寫入目標並緩沖區被清除。 內存中沒有任何東西。

StringBuilder sb1 = new StringBuilder();
     sb1.append(vid);
     String videoid=sb1.toString();

這是一種方法,另一種方式:

     String videoId = new String(new Integer(rs.getInt("videoid")));

另外,了解java堆空間的分配方式和方式:

    -Xms<size>        set initial Java heap size
    -Xmx<size>        set maximum Java heap size
    -Xss<size>        set java thread stack size

為Java程序設置最小堆為64 MB,最大堆為256 MB HelloWorld:java -Xms64m -Xmx256m HelloWorld如果使用IDE,則必須更改服務器啟動中的params。 HTH

您的堆太小,無法容納應用程序分配的所有對象。

最簡單的解決方案是增加堆大小 例如-Xms1g -Xmx1g

或者,您可以嘗試分析應用程序以查看內存分配的來源並優化該代碼路徑。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM