java. lang.OutOfMemoryError:
I'm trying to create a video file from the bytes retrieved from the database The plan worked well a few hours ago After uploading a large file, when I try to retrieve it, it generates an error 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 tell me what this mistake tells me I need to correct it Thank you
Solution
here,
byte[] videoData = rs.getBytes("videofull");
You store the entire file content in the memory of the server You know, a byte of byte [] takes up a byte of JAVA memory If you have, for example, only 500MB of memory and files exceeding 500MB, you will get this error Please note that when 10 users request 50MB video files at the same time, you will also get it Therefore, as other answers show, increasing JAVA memory is only a temporary solution without careful consideration
You need to get it in the style of InputStream so that only a few (kilobytes) bytes are allocated internally as the stream buffer in memory instead of the entire file content
InputStream videoData = rs.getBinaryStream("videofull");
Then use ioutils #copy() to write it to the desired output stream (don't forget to close them in finally!)
FileOutputStream output = new FileOutputStream(file); try { IoUtils.copy(videoData,output); } finally { IoUtils.closeQuietly(output); IoUtils.closeQuietly(videoData); }