执行JAVA Mapping时出现OutOfMemory异常

时间:2015-09-30 05:42:59

标签: java base64 sap

我必须传输大文件(500 MB + ...也可以是1GB大小)。这些文件必须是base64编码的,编码的字符串必须放在XML文件中。虽然我的下面的代码适用于较小的文件(30 - 50 MB),但对于大于100 MB的文件,它会失败。 我正在使用SUN的sun64编码器(sun.misc.BASE64Encoder)。

public void execute(InputStream inputstream, OutputStream outputstream) throws StreamTransformationException{
        try
        {
            String sourceFileName = "test_file";
            String ReceiverStr = "";
            //2. Convert input data in Base64Encoded string
            BASE64Encoder encoder = new BASE64Encoder();
            byte input[] = new byte[inputstream.available()];

            inputstream.read(input);
            String base64Encoded = encoder.encode(input);
            //3. Build the SOAP request format
            String serverUrl = "http://website/url";

            String soapEnvelope = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:soap=\"http://schemas.microsoft.com/sharepoint/soap/\">";
            String soapHeader = "<soapenv:Header/><soapenv:Body><soap:CopyIntoItems><soap:SourceUrl>C:\\Users\\Desktop\\test_file.txt</soap:SourceUrl><soap:DestinationUrls><soap:string>" + serverUrl + "</soap:string></soap:DestinationUrls><soap:Fields><soap:FieldInformation " + "Type=" + "\"Text\"" + " DisplayName=\"" + sourceFileName + "\"" + " InternalName=\"" + sourceFileName + "\"" + " Id=\"deff4b5c-b727-414c-893d-c56a8e12455f\"" + " Value=\"" + sourceFileName + "\"/></soap:Fields>";
            String soapStream = "<soap:Stream>" + base64Encoded + "</soap:Stream>";
            ReceiverStr = soapEnvelope + soapHeader + soapStream + "</soap:CopyIntoItems></soapenv:Body></soapenv:Envelope>";
            //4. Write the SOAP request to receiver channel
            outputstream.write(ReceiverStr.getBytes());
        }
        catch(Exception e) {
            throw new StreamTransformationException(e.toString());  
        }
    }

当我尝试在运行时看到该消息时,则不显示整个消息,并在base64Encoded字符串中截断它。 下面是我的系统在执行JAVA代码时看到的错误。 enter image description here 请注意,我的服务器设置可以轻松传输1GB +文件,而不会出现任何JAVA堆大小错误或文件截断。 能告诉我如何使用上述逻辑处理大文件吗?

谢谢,

阿布舍克巴克。

3 个答案:

答案 0 :(得分:1)

您的代码存在很多问题。 首先,我建议切换到OutputStreamWriter而不是OutputStream作为参数(您不是在写二进制数据,而是在编写字符数据)。

首先写出标题,然后开始处理输入流,例如8192字节(不要使用inputstream.available(),你不需要它)。如果您不知道处理流的“标准”方式,请浏览Java IO Essentials。基本上你读取了一大块数据,将其转换为Base64将其写出并重复(直到输入流耗尽)。注意!你必须确保编码大小可被3整除的块(除了最后一个块),否则会应用填充,这会弄乱结果。最后一个块可以有填充。

之后您可以编写页脚,整个过程几乎不会占用任何内存。

答案 1 :(得分:0)

查看代码,将数据存储三次:

第一次是来自输入流的字节数组。第二次是在编码的String中,最后将它写入输出流。

您可以做些什么来优化这一点是将读取与输入流/编码分开,并将编码字符串写入输出流。这样,一旦编码就可以释放输入字节数组,并且可以释放内存。更好的解决方案是编码器直接写入输出流或直接写入encoding output stream

但是,您仍然需要考虑可以处理的最大文件大小,并相应地调整堆设置:How to deal with "java.lang.OutOfMemoryError: Java heap space" error (64MB heap size)

答案 2 :(得分:-1)

启动应用程序时,您配置了哪种堆大小? 据我所知,默认堆大小为256kb,并且由于您将整个文件一次编码为base64,因此需要将堆大小设置为文件大小的至少1.5倍。

查看如何使用set并使用VM-argument&#34; -Xmx&#34;。