Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何修复java.lang.OutOfMemoryError:java堆空间错误?_Java_Tomcat_Jersey_Out Of Memory_Docushare - Fatal编程技术网

如何修复java.lang.OutOfMemoryError:java堆空间错误?

如何修复java.lang.OutOfMemoryError:java堆空间错误?,java,tomcat,jersey,out-of-memory,docushare,Java,Tomcat,Jersey,Out Of Memory,Docushare,我有一个32 MB大小的文件,我已经从DocuShare服务器下载到DocuShare临时文件夹。我正在尝试从中读取文件内容以创建文件。我在URL编码base64内容时出错。 当我在一个简单的java应用程序中运行相同的代码时,我没有得到任何异常。但当我在DocuShare服务中使用相同的代码来获取文档内容时,我得到了异常。 HTTP状态500-org.glassfish.jersey.server.ContainerException:java.lang.OutOfMemoryError:ja

我有一个32 MB大小的文件,我已经从DocuShare服务器下载到DocuShare临时文件夹。我正在尝试从中读取文件内容以创建文件。我在URL编码base64内容时出错。 当我在一个简单的java应用程序中运行相同的代码时,我没有得到任何异常。但当我在DocuShare服务中使用相同的代码来获取文档内容时,我得到了异常。 HTTP状态500-org.glassfish.jersey.server.ContainerException:java.lang.OutOfMemoryError:java堆空间

File file = new File(filePath);
FileInputStream fileInputStreamReader = new FileInputStream(file);
byte[] bytes = new byte[(int)file.length()];
fileInputStreamReader.read(bytes);
String encodedBase64 = String encodedBase64 = java.util.Base64.getEncoder().encodeToString(bytes);
String urlEncoded = URLEncoder.encode(encodedBase64);
org.glassfish.jersey.server.ContainerException:java.lang.OutOfMemoryError:java堆空间

File file = new File(filePath);
FileInputStream fileInputStreamReader = new FileInputStream(file);
byte[] bytes = new byte[(int)file.length()];
fileInputStreamReader.read(bytes);
String encodedBase64 = String encodedBase64 = java.util.Base64.getEncoder().encodeToString(bytes);
String urlEncoded = URLEncoder.encode(encodedBase64);
如何修复此错误?
是否需要增加tomcat堆大小?

如果您有大文件,根据文件大小,您将始终遇到OOM错误。如果您的目标是使用Apache Commons base64流进行base64编码


有两种方法可以解决此问题

  • 您可以增加堆大小,但在我看来,这是一个糟糕的解决方案,因为如果您收到多个并行请求或试图处理更大的文件,您将遇到相同的问题

  • 您可以优化算法—您可以以流式方式处理文件,而不是将文件的多个副本存储在内存中,从而在内存中保存不超过几个KB:

    import java.io.InputStream;
    import java.io.OutputStream;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.Base64;
    
    public class Launcher {
        public static void main(String[] args) throws Exception {
            final Path input = Paths.get("example");
            final Path output = Paths.get("output");
    
            try (InputStream in = Files.newInputStream(input); OutputStream out = Base64.getUrlEncoder().wrap(Files.newOutputStream(output))) {
                final byte[] buffer = new byte[1024 * 8];
    
                for (int read = in.read(buffer); read > 0; read = in.read(buffer)) {
                    out.write(buffer, 0, read);
                }
            }
        }
    }
    

  • PS:如果你真的需要URL编码器,你必须创建它的流式版本,但我认为URL安全的base64已经足够了。

    base64将每3个字节转换成4个字母。这意味着您可以分块读取数据,并以与解码整个文件相同的方式对其进行解码

    试试这个:

           File file = new File(filePath);
           FileInputStream fileInputStreamReader = new FileInputStream(file);
           StringBuilder sb = new StringBuilder();
           Base64.Encoder encoder = java.util.Base64.getEncoder();
           int bufferSize = 3 * 1024; //3 mb is the size of a chunk
           byte[] bytes = new byte[bufferSize]; 
           int readSize = 0;
    
           while ((readSize = fileInputStreamReader.read(bytes)) == bufferSize) {
                sb.append(encoder.encodeToString(bytes));
           }
    
           if (readSize > 0) {
                bytes = Arrays.copyOf(bytes, readSize);
                sb.append(encoder.encodeToString(bytes) );
           }
    
           String encodedBase64  = sb.toString();
    

    首先,当出现此错误时,应该确定堆的实际使用情况。您似乎正在存储此文件内容的多个副本。(此外,您应该首先使用URL安全的Base64字符集。)为JVM提供足够的内存或优化代码。增加堆大小!奇怪的为什么你会提出一些你自己认为不好的解决方案?让我指出,这根本不是编程解决方案。你应该删除你的第1点。@MohammadRakibAmin我不推荐它——恰恰相反。我只是说这是一个可能的解决办法。回答得好。提到增加堆大小很重要,因为OP提到了它。增加-Xmx将使OOM误差在小范围内消失。解决方案2是一个更好的答案,因为它降低了应用程序的峰值堆需求。在servlet容器中,将32MB文件作为单个块返回也可能最终为每个服务于大文件的请求线程分配一个大的非堆直接缓冲区。某些容器在完成请求后会保存这些内容,直到请求线程被终止,这可能永远不会被终止。@MohammadRakibAmin这是一个选项。这可能(通常)不是一个好的选择,但它是一个选择。在某些情况下,这很可能是必要的,例如,如果您必须在内存中保留固定数量的资源,而分配的总资源不足以保存这些资源。对于您的信息,您正在忽略中的详细答案,使用有限的存储空间。最重要的是,OP询问是否需要增加分配的堆大小。他没有问如何增加堆大小。否则我就不会对错树吠叫了。在题为“如何修复”的问题中,仅仅关闭OutOfMemory错误不能成为编程解决方案