我们需要发送非常大的SOAP消息(多部分,MTOM),比如大约1或2千兆字节。 有时,该过程最终会出现以下OOM:
java.lang.OutOfMemoryError: Java Heap Space
at java.util.Arrays.copyOf(Arrays.java:2479)
at java.io.ByteArrayOutputStream.toByteArray(ByteArrayOutputStream.java:203)
at com.ibm.ws.webservices.engine.transport.channel.OutboundOutputStream.toByteArray(OutboundOutputStream.java:100)
at com.ibm.ws.webservices.engine.transport.http.HttpOutboundChannelConnection.prepareHttpRequestHeaders(HttpOutboundChannelConnection.java:2027)
at com.ibm.ws.webservices.engine.transport.http.HttpOutboundChannelConnection.sendSOAPRequest(HttpOutboundChannelConnection.java:374)
at com.ibm.ws.webservices.engine.transport.http.HTTPSender.invoke(HTTPSender.java:745)
at com.ibm.ws.webservices.engine.PivotHandlerWrapper.invoke(PivotHandlerWrapper.java:264)
at com.ibm.ws.webservices.engine.PivotHandlerWrapper.invoke(PivotHandlerWrapper.java:264)
at com.ibm.ws.webservices.engine.WebServicesEngine.invoke(WebServicesEngine.java:336)
at com.ibm.ws.webservices.engine.client.Connection.invokeEngine(Connection.java:970)
at com.ibm.ws.webservices.engine.client.Connection.invoke(Connection.java:761)
at com.ibm.ws.webservices.engine.soap.SOAPConnectionImpl.call(SOAPConnectionImpl.java:223)
at com.ibm.ws.webservices.engine.soap.SOAPConnectionImpl.call(SOAPConnectionImpl.java:163)
据我所知,问题是由于使用了ByteArrayOutputStream,这在使用非常庞大的流时看起来不合适。
在堆栈跟踪之后,它需要堆中的整个消息内容(作为字节数组)至少有2个副本。
所以问题是,是否有人知道通过堆消耗更好地实现SAAJ? 或者可能是这个SAAJ的IBM实现的一些解决方法?
答案 0 :(得分:1)
假设IBM的SAAJ实现并不完全是脑力,我希望它只在没有启用HTTP分块的情况下将消息转换为字节数组,并且需要在发送之前计算消息的长度。因此,首先要确保启用分块。
我不认为SAAJ定义了一种启用分块的标准方法,但您可能想尝试在消息上设置相应的HTTP标头:
soapMessage.getMimeHeaders().addHeader("Transfer-Encoding", "chunked");
SAAJ的实施很可能会尊重这一点。