简体   繁体   English

java.lang.OutOfMemoryError:

[英]java.lang.OutOfMemoryError:

I'm trying to create video files from the bytes retrieved from the database. 我正在尝试从数据库中检索的字节创建视频文件。 The program was worked well before few hours. 该计划在几个小时之前运作良好。 After uploading a large file, When I try to retrieve it, It is producing the error java.lang.OutOfMemoryError: 上传大文件后,当我尝试检索它时,它产生错误java.lang.OutOfMemoryError:

My code is: 我的代码是:

    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);
    } 

Console output is: 控制台输出是:

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)

Please anyone tell me what this error tells. 请有人告诉我这个错误告诉了什么。 What I need to correct in it.......Thanks..... 我需要纠正它.......谢谢.....

Here, 这里,

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

You're storing the entire file contents in server's memory. 您将整个文件内容存储在服务器的内存中。 You know, one byte of a byte[] eats one byte of Java's memory. 你知道, byte[]一个字节占用Java内存的一个字节。 If you've eg only 500MB memory and the file is over 500MB, then you'll get exactly this error. 如果你只有500MB内存并且文件超过500MB,那么你将得到这个错误。 Note that you will also get it when 10 users concurrently request a video file of 50MB. 请注意,当10个用户同时请求50MB的视频文件时,您也会得到它。 So increasing the Java memory as suggested by other answers is only a temporary solution and not really well thought out. 因此,如其他答案所示,增加Java内存只是一个临时解决方案,并没有经过深思熟虑。

You need to obtain it in flavor of an InputStream instead so that would internally allocate only a few (kilo)bytes as streaming buffer in memory instead of the entire file contents. 您需要在InputStream风格中获取它,以便在内部仅分配几个(千字节)字节作为内存中的流缓冲区而不是整个文件内容。

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

And write it to the desired output stream using IOUtils#copy() instead (don't forget to close them in the finally!). 然后使用IOUtils#copy()将其写入所需的输出流(不要忘记在finally中关闭它们!)。

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

As the size of your video files is large it has finished all the memory in heap. 由于视频文件的大小很大,它已经完成了堆中的所有内存。 You got to increase your heap size by setting the VM arguments as -Xmx1024m . 您必须通过将VM参数设置为-Xmx1024m来增加堆大小。 this will increase your heap space to 1 gb . 这会将堆空间增加到1 GB。 If the problem still persist then you have to use java vm visual to analyse which part of your program is consuming more memory and u shud work on other ways to reduce it. 如果问题仍然存在,那么你必须使用java vm visual来分析你的程序的哪个部分正在消耗更多的内存,并且你可以通过其他方式来减少它。 Increasing the Heap space more than 1 gb is not a good solution to over come heap space issue . 增加堆空间超过1 gb并不是解决堆空间问题的好方法。

If your running your program from an IDE like eclipse set ur configuration in run as configuration mode. 如果您从像eclipse这样的IDE运行程序,请在运行配置模式下设置配置。

The error says you are out of memory. 错误说你内存不足。 You need to load less stuff into memory, or increase the total amount of memory available. 您需要将更少的内容加载到内存中,或者增加可用的内存总量。

The error tells: 错误告诉:

OutOfMemoryError: Java heap space

You need more heap space: you can configure the VM to use more heap Space. 您需要更多堆空间:您可以将VM配置为使用更多堆空间。

Option -Xmx 选项-Xmx

Example: -Xmx256m for 256 Megabytes maximum heap space 示例: -Xmx256m ,最大堆空间为256 MB

Use the -Xmx flag to increase the heap space allocated to your JVM. 使用-Xmx标志可以增加分配给JVM的堆空间。 -Xmx1500m for example. -Xmx1500m例如。

If executeing from a cli this is easy 如果从cli执行,这很容易

java -Xmx2000m youMainJavaFile

If you are executing from eclipse or the like, youll need to go into the options and tell it to add this flag when execing the JVM. 如果从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 . 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

Says Oracle docs, this means you should increase the memory limitation of your JVM which runs your program. Oracle文档说,这意味着您应该增加运行程序的JVM的内存限制。 Increasing heap size: 增加堆大小:

JVM_ARGS="-Xmx1024m"

This sets the heap size to 1024mb. 这会将堆大小设置为1024mb。 Or you can do this in your IDE in run configruations giving -Xmx1024m as VM parameter will work properly. 或者您可以在IDE中执行此操作,在运行配置中给出-Xmx1024m因为VM参数将正常工作。

Inside IOUtils.write use output.flush(), so that the buffered bytes will be written to destination and buffer get cleared up. 在IOUtils.write里面使用output.flush(),这样缓冲的字节就会被写入目标并缓冲区被清除。 Nothing stays in memory. 内存中没有任何东西。

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

That is one way to do it, heres another way : 这是一种方法,另一种方式:

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

Also, learn what/how the java heap space is allocated : 另外,了解java堆空间的分配方式和方式:

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

To set minimum heap to 64 MB and maximum heap 256 MB for a Java program HelloWorld : java -Xms64m -Xmx256m HelloWorld If you are using an IDE you will have to change the params in your server startup. 为Java程序设置最小堆为64 MB,最大堆为256 MB HelloWorld:java -Xms64m -Xmx256m HelloWorld如果使用IDE,则必须更改服务器启动中的params。 HTH HTH

Your heap is too small to hold all the objects allocated by your application. 您的堆太小,无法容纳应用程序分配的所有对象。

The easiest solution is to increase the heap size . 最简单的解决方案是增加堆大小 Eg -Xms1g -Xmx1g 例如-Xms1g -Xmx1g

Or, you could try to analyze the app to see where is the memory allocation coming from and optimize that code path. 或者,您可以尝试分析应用程序以查看内存分配的来源并优化该代码路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM