3

データベースから取得したバイトからビデオ ファイルを作成しようとしています。プログラムは、数時間前にうまく機能しました。大きなファイルをアップロードした後、それを取得しようとすると、エラーが発生しています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)

このエラーの意味を教えてください。その中で修正する必要があること.......ありがとう.....

4

9 に答える 9

11

ここ、

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

ファイルの内容全体をサーバーのメモリに保存しています。ご存知のように、a のbyte[]1 バイトは Java のメモリを 1 バイト消費します。たとえば、メモリが 500MB しかなく、ファイルが 500MB を超える場合、まさにこのエラーが発生します。10 人のユーザーが同時に 50 MB のビデオ ファイルを要求した場合にも取得されることに注意してください。したがって、他の回答で示唆されているように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);
}
于 2013-02-20T20:23:21.963 に答える
2

ビデオ ファイルのサイズが大きいため、ヒープ内のすべてのメモリが終了しました。VM 引数を -Xmx1024m に設定して、ヒープ サイズを増やす必要があります。これにより、ヒープ領域が 1 GB に増加します。それでも問題が解決しない場合は、java vm visual を使用して、プログラムのどの部分がより多くのメモリを消費しているかを分析し、それを減らすために他の方法で作業する必要があります。ヒープ スペースを 1 GB 以上に増やすことは、ヒープ スペースの問題を解決する良い解決策ではありません。

eclipse のような IDE からプログラムを実行している場合は、設定を run as 設定モードに設定します。

于 2013-02-20T19:37:26.100 に答える
1

IOUtils.write 内で output.flush() を使用して、バッファリングされたバイトが宛先に書き込まれ、バッファがクリアされるようにします。何も記憶に残りません。

于 2013-02-20T20:00:55.060 に答える
1
StringBuilder sb1 = new StringBuilder();
     sb1.append(vid);
     String videoid=sb1.toString();

それはそれを行う1つの方法ですが、別の方法は次のとおりです。

     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 プログラム HelloWorld の最小ヒープを 64 MB、最大ヒープを 256 MB に設定するには: java -Xms64m -Xmx256m HelloWorld IDE を使用している場合は、サーバーの起動時にパラメーターを変更する必要があります。HTH

于 2013-02-20T20:01:12.990 に答える
1

エラーは、メモリが不足していることを示しています。メモリにロードするものを減らすか、使用可能なメモリの総量を増やす必要があります。

于 2013-02-20T19:25:24.647 に答える