繁体   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